esp8266 Digest авторизация принятый урл со стороннего контроллера

3d_killer
Offline
Зарегистрирован: 13.06.2018

Добрый вечер всем, возникла проблема при разборе Digest авторизации, код взят из примера, сервер указал локальный на котором крутится апач, код взят из примера к модулю:

volatile bool send_data=0;
static String email_my = "test";
static String password_my = "test";
const char *myserver = "http://test";
String url = "";
//*************************************************************************************
//Авторизация
//*************************************************************************************
String exractParam(String& authReq, const String& param, const char delimit) 
  {
    int _begin = authReq.indexOf(param);
    if (_begin == -1) 
      {
        return "";
      }
    return authReq.substring(_begin + param.length(), authReq.indexOf(delimit, _begin + param.length()));
  }
String getCNonce(const int len) 
{
    static const char alphanum[] =
    "0123456789"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefghijklmnopqrstuvwxyz";
    String s = "";
    for (int i = 0; i < len; ++i) 
      {
        s += alphanum[rand() % (sizeof(alphanum) - 1)];
      }
    return s;
}
String getDigestAuth(String& authReq, String username, String password, String url,unsigned int counter) 
{
  // extracting required parameters for RFC 2069 simpler Digest
  String realm = exractParam(authReq, "realm=\"", '"');
  String nonce = exractParam(authReq, "nonce=\"", '"');
  String cNonce = getCNonce(8);
  char nc[9];
  snprintf(nc, sizeof(nc), "%08x", counter);
  // parameters for the RFC 2617 newer Digest
  MD5Builder md5;
  md5.begin();
  md5.add(username + ":" + realm + ":" + password);  // md5 of the user:realm:user
  md5.calculate();
  String h1 = md5.toString();
  md5.begin();
  md5.add(String("GET:") + url);
  md5.calculate();
  String h2 = md5.toString();
  md5.begin();
  md5.add(h1 + ":" + nonce + ":" + String(nc) + ":" + cNonce + ":" + "auth" + ":" + h2);
  md5.calculate();
  String response = md5.toString();
  String authorization = "Digest username=\"" + username + "\", realm=\"" + realm + "\", nonce=\"" + nonce +
                         "\", uri=\"" + url + "\", algorithm=\"MD5\", qop=auth, nc=" + String(nc) + ", cnonce=\"" + cNonce + "\", response=\"" + response + "\"";
  Serial.println(authorization);
  return authorization;
}
//*************************************************************************************
//Авторизоваться и послать данные в порт
//*************************************************************************************
void SendData()
{
  WiFiClient client;
  HTTPClient http;
  Serial.print("[HTTP] begin...\n");
  // configure traged server and url
  http.begin(client, String(myserver) + String(url));
  const char *keys[] = {"WWW-Authenticate"};
  http.collectHeaders(keys, 1);
  Serial.print("[HTTP] GET...\n");
  // start connection and send HTTP header
  int httpCode = http.GET();
  if (httpCode > 0) 
  {
    String authReq = http.header("WWW-Authenticate");
    //Serial.println(authReq);
    String authorization = getDigestAuth(authReq, email_my, password_my, String(url), 1);
    http.end();
    http.begin(client, String(myserver) + String(url));
    http.addHeader("Authorization", authorization);
    int httpCode = http.GET(); 
    if (httpCode > 0) 
      { 
        String payload = http.getString();
        Serial.println(payload);
        //Разбор пришедшего JSON
        //Parsing(payload);
        MySerial.println(payload);
      } 
    else 
      {
        Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
      }
  } 
  else 
  {
    Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
  }
  http.end();    
}

блок setup не пишу чтобы не засорять код, модуль подключается к WIFI и идет метод loop:

void loop(void) 
  {
        ReadSerial();
if(send_data==1){SendData();send_data=0;}

  }
void ReadSerial()
  {
    static String data="";
    if(MySerial.available()>0)
      {
        char temp=MySerial.read();
        if (temp == '\n')
          {
            Serial.println(data);
             url = data;
             data="";
             MySerial.flush();
             send_data=1;
          }
        else
          {
            data+= temp;
          }
      }
  }

строка которая приходит с другого контроллера имеет вид: \?t=10 ее я вижу при выводе Serial.println, но сервер отвечает 400 Bad Request, однако если я присваиваю вместо url = data; url="\?t=10"; Все отлично выполняется и от сервера я получаю ответ, почему так происходит? как решить данную проблему?

3d_killer
Offline
Зарегистрирован: 13.06.2018

в тексте ошибся в последнем, слеш используется / а не как я написал

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

В функции ReadSerial в data попадает также символ '\r', если перевод строки настроен как \r\n. Возможно, это играет роль.

3d_killer
Offline
Зарегистрирован: 13.06.2018

Так у меня другой контроллер просто отправляет Serial.println("/?t=10"); Это я не вручную пишу (в мониторе порта)

3d_killer
Offline
Зарегистрирован: 13.06.2018

А вы правы, только как это убрать чтобы не отправлять доп знаки, сейчас отправил с контроллера вот так:

Serial.print("/?time=10@");

а в приеме написал вот так:

if(MySerial.available()>0)
      {
        //Зажигаем светодиод 
        digitalWrite(led, 0);
        //Читаем символ
        char temp=MySerial.read();
        if (temp == '@')
          {
            url = data;
            Serial.println(url);
             data="";
             MySerial.flush();
          }
        else
          {
            data+= temp;
          }
      }

И все прошло, только хотелось бы не добавлять к урл дополнительные знаки

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

3d_killer пишет:

Так у меня другой контроллер просто отправляет Serial.println("/?t=10"); Это я не вручную пишу (в мониторе порта)

println добавляет в конец печатаемых данных два символа - \r\n.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

3d_killer пишет:

А вы правы, только как это убрать чтобы не отправлять доп знаки

Вы не сами писали, что ли? У вас есть сравнение с '\n'. Что мешает сделать else if и сравнение с '\r', при этом в блоке ничего не плюсовать к data?

3d_killer
Offline
Зарегистрирован: 13.06.2018

Да так заработало, else if(temp == '\r'){} спасибо большое