Ошибка 401 в WEB API 2 при большом количестве запросов с устройства Android

Я разрабатываю приложение для Android и веб-сервис, которые общаются. Мой веб-сервис работает в WEB API 2 с аутентификацией на носителе токена.

Моя проблема заключается в том, что, когда я отправляю слишком много запросов (~20 запросов за 15 секунд) в мою веб-службу из моего приложения для Android, ответ WS с

    “401” : “Authorization has been denied for this request”

Это происходит ТОЛЬКО на рабочем сервере (хостер Amen) И с Android-устройства. Например, если я попробую с Почтальоном, все работает нормально. Так что это связано с моим рабочим сервером и / или моим запросом приложения для Android.

Код для доступа к веб-сервису

    URL obj = new URL(SERVEUR_URL + url);
    HttpURLConnection con = (HttpURLConnection) obj.openConnection();
    con.setRequestMethod("GET");
    con.setRequestProperty("Authorization", "Bearer " + token);
    con.setRequestProperty("Content-Type", "application/json");

    int responseCode = con.getResponseCode();
    String responseMessage = con.getResponseMessage();

Поставщик проверки подлинности в моей веб-службе является поставщиком по умолчанию. Без изменений.

Запрос из моего приложения для Android (не работает каждый раз)

    GET http://api.xxxx.com/api/Weesps/GetAvailableWeesps HTTP/1.1
    Authorization: Bearer XXXX
    Content-Type: application/json
    User-Agent: Dalvik/2.1.0 (Linux; U; Android 6.0; Google Nexus 5X - 6.0.0 - API 23 - 1080x1920 Build/MRA58K)
    Host: api.xxxx.com
    Connection: Keep-Alive
    Accept-Encoding: gzip

Запрос от Почтальона (работа каждый раз)

    GET http://api.xxxx.com/api/Weesps/GetAvailableWeesps HTTP/1.1
    Host: api.xxxx.com
    Connection: keep-alive
    Authorization: Bearer XXXX
    Cache-Control: no-cache
    User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36         (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36
    Postman-Token: bca55154-775d-9709-7a8b-4793393890ad
    Accept: */*
    Accept-Encoding: gzip, deflate, sdch
    Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
    Cookie: dadaproaffinity=14ff51cc869a14d3552485cb4ceee1faa1be7165cc5d4b0e2b19370f11afcbea

Что я пробовал:

  • Воспроизведите эту ошибку на локальном компьютере: она отлично работает на локальном сервере (веб-серверы и серверы SQL) из приложения Android или из Почтальона.
  • Я проверяю, что токен был отправлен правильно в каждом запросе
  • Запрос от Android всегда одинаков
  • Попытка добавить отсутствующий заголовок в мой запрос приложения для Android

Я трачу два дня на эту проблему и читаю много сообщений stackru, но никто не помогает мне. Спасибо за вашу помощь.

ОБНОВЛЕНИЕ 1:

С Fiddler я увидел, что в GET-запросе от Postman они были заголовком Cookie. Этот файл cookie отправляется, когда мы запрашиваем токен на предъявителя.

Пример ответа токена с сервера

    HTTP/1.1 200 OK
    Cache-Control: no-cache
    Pragma: no-cache
    Content-Length: 691
    Content-Type: application/json;charset=UTF-8
    Expires: -1
    Server: Microsoft-IIS/8.5
    Set-Cookie: .AspNet.Cookies=XXXX; path=/; HttpOnly
    X-Powered-By: ASP.NET
    X-Powered-By: ARR/2.5
    Date: Tue, 31 May 2016 16:55:39 GMT

            {"access_token":"XXXX","token_type":"bearer","expires_in":1209599,"userName":"Foo",".issued":"Tue, 31 May 2016 16:55:40 GMT",".expires":"Tue, 14 Jun 2016 16:55:40 GMT"}

Фиддлер и Почтальон сохранили этот куки-файл и автоматически помещают его в запросы к API (например, в блоке кода "Запрос от Почтальона"). Когда я удаляю cookie из GET-запроса Postman, он не работает (как и мое приложение для Android).

Теперь возникает вопрос: почему WEB API 2 отправляет cookie вместо использования только токена? И почему токен отлично работает в первых запросах и не работает должным образом для следующих запросов?

2 ответа

Решение

Наконец я получил ответ:

Мой веб-сервис отправляет файл cookie с именем "dadaproaffinity" при первом запросе запроса. Этот Cookie был автоматически помещен в следующий запрос Почтальоном, но не Android HttpUrlConnection. Итак, я просто беру этот Cookie и теперь просто добавляю этот Cookie при каждом запросе токена.

Но: этот файл cookie отправляется IIS, а не моим веб-сервисом! Вот почему он работает на локальном, но не на рабочем сервере. Я гуглил это печенье, и об этом очень мало отзывов. Единственное, что я нахожу на английском:

    Technical Cookie of IIS Server hosting the site.
    Need to route to the correct server session, in order to keep it active

У кого-нибудь есть больше информации об этом IIS Cookie?

В соответствии с потоком ASP.NET WebAPI2, который вы видите в нижней части этой страницы, кажется, что ваши запросы всегда проходят проверку подлинности, но иногда не могут быть авторизованы.

Итак, IMO, AuthorizationFilter [Authorize] отклоняет некоторые ваши запросы по неизвестной причине. Я хотел бы предложить отбросить запрос, который получает ваш API, а также идентификационные данные утверждений, прикрепленные к токену. Попытайтесь увидеть, есть ли различия между ними, когда у вас есть успешный ответ и когда у вас есть 401.

Таким образом, вы сможете определить, является ли ваш запрос искаженным, является ли это неправильной идентификацией утверждений или если это AuthorizationFilter, который отклоняет вас по другой причине (например, слишком много запросов или другое).

Удачи!

ОБНОВЛЕНИЕ 1 В соответствии с вашими новыми данными, я думаю, что ваш веб-API настроен на использование аутентификации токена и cookie.

Я вижу, что у вас есть два решения: 1 ° / Сохраните возвращенный файл cookie в своем приложении Android и используйте его для следующих вызовов. Самый простой и быстрый способ решения вашей проблемы без изменения всего вашего API, но вы сохраняете куки авторизации: это может привести к проблеме безопасности (CSRF-атакам).

2 ° / Вы можете проверить, как ваши фильтры аутентификации и авторизации настроены на отключение аутентификации с использованием cookie-файлов и полагаются только на аутентификацию токена: следовательно, все запросы и ваш API-интерфейс заставят использовать только токен и предотвратит вас от CSRF-атак. Сложнее, потому что вы должны копаться в конфигурации веб-API.

Проверьте следующие ссылки (извините, поскольку у меня пока недостаточно репутации, чтобы публиковать более 2 ссылок на сообщение, вы найдете их в виде текста в конце моего ответа):

  • ASP.net Secure a Web API 2.2 [2]: Из главы "Настройка сервера авторизации" внизу
  • Статья MSDN о безопасности веб-API [3]: более общая и техническая информация о безопасности веб-API, о том, как ее защитить и о атаках CRSF

  • Stackru.NET cookie и аутентификация токена [4]: ​​проверьте ответ Дэвида Банистера, я думаю, что это именно то, что вы хотите сделать: использовать токен только для всех ваших вызовов API.

  • Фильтр авторизации Stackru и аутентификация [5]: дополнительная информация о таких механизмах для вашего API

И наконец

  • Проверка подлинности файлов cookie с помощью веб-API и кодов 401 [6]: похоже на вашу настоящую проблему, не так ли?

Я надеюсь, что это поможет вам, удачи!

// Ссылки

2: www.asp.net/web-api/overview/security/individual-accounts-in-web-api

3: msdn.microsoft.com/en-us/magazine/dn201748.aspx

4: stackru.com/questions/22568409/mvc-net-cookie-authenticated-system-acessing-a-web-api-with-token-authenticatio

5: stackru.com/questions/21231751/authorize-filter-and-authentication

6: brockallen.com/2013/10/27/using-cookie-authentication-middleware-with-web-api-and-401-response-codes/

Другие вопросы по тегам