当 Android 设备有很多请求时,WEB API 2 上的错误 401

Error 401 on WEB API 2 when there is lot of request from Android device

我正在开发一个 Android 应用程序和一个可以通信的 Web 服务。我的 Web 服务在 WEB API 2 中,带有令牌持有者身份验证。

我的问题是,当我从我的 Android 应用向我的 Web 服务发送太多请求(15 秒内约 20 个请求)时,WS 响应

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

这只发生在生产服务器(Amen 主机)和 Android 设备上。例如,如果我尝试使用 Postman,一切正常。所以这与我的生产服务器 and/or 我的 android 应用程序请求有关。

访问Web服务的代码

    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();

我的 Web 服务上的身份验证提供程序是默认的。没有修改。

来自我的 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

Postman的要求(每次都工作)

    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

我尝试过的:

我在这个问题上花了两天时间,阅读了很多 Whosebug 帖子,但没有人帮助我。 感谢您的帮助。

更新 1:

使用 Fiddler,我在 Postman 的 GET 请求中看到,它们是一个 Cookie header。当我们请求不记名令牌时发送此 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"}

Fiddler 和 Postman 保存了这个 cookie,并自动将其放入对 API 的请求中(例如“来自 Postman 的请求”代码块)。当我从 Postman GET 请求中删除 cookie 时,它​​不起作用(就像我的 android 应用程序一样)。

现在,问题是:为什么 WEB API 2 发送 cookie 而不是仅使用令牌?以及为什么令牌在第一个请求中工作得很好,而在接下来的请求中却不能正常工作?

根据 ASP.NET WebAPI2 flow 您可以在该页面的底部看到,您的请求似乎总是经过身份验证但有时无法获得授权。

在我看来,AuthorizationFilter[Authorize] 出于未知原因拒绝了您的一些请求。我的建议是转储您的 API 收到的请求以及附加到令牌的声明身份。试试看你响应成功和401响应有什么区别

这样,您可以确定是您的请求格式不正确,是声明标识不正确,还是 AuthorizationFilter 出于其他原因拒绝您(例如查询太多否则)。

祝你好运!

更新 1 根据您的新输入,我认为您的 Web API 配置为同时使用令牌和 cookie 身份验证。

我在这里看到的是您有两个解决方案: 1°/ 将返回的 cookie 存储在您的 Android 应用程序中,并将其用于下一次调用。无需更改所有 API 即可解决问题的最简单和最快的方法,但您存储授权 cookie:它可能导致安全问题(CSRF 攻击)。

2°/ 您可以检查您的身份验证和授权过滤器如何设置为禁用 cookie 身份验证并仅依赖令牌身份验证:因此它将强制所有请求和您的 API 仅使用令牌并将防止您遭受 CSRF 攻击。更复杂,因为您必须深入研究您的网络 API 配置。

检查以下链接(抱歉,因为我还没有足够的声誉 post 每个 post 超过 2 个链接,您会在我的末尾找到它们作为文本答案):

  • ASP.net 保护 Web API 2.2[2]:来自底部的 "Configuring the Authorization Server" 章节
  • Web 上的 MSDN 文章 API 安全性[3]:有关 Web api 安全性、如何保护它和 CRSF 攻击的更多一般和技术信息

  • Whosebug .NET cookie 和令牌身份验证[4]:查看 David Banister 的回答,我认为这正是您想要做的:仅对所有 API 调用使用令牌。

  • Whosebug 授权过滤器和身份验证[5]:有关此类机制的更多信息 API

最后

  • 使用网络 API 和 401 代码[6] 的 Cookie 身份验证:听起来像您的实际问题,不是吗?

希望对你有所帮助,祝你好运!

// 链接

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

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

4: 计算器。com/questions/22568409/mvc-net-cookie-authenticated-system-acessing-a-web-api-with-token-authenticatio

5: 计算器。com/questions/21231751/authorize-filter-and-authentication

6: 布罗卡伦。com/2013/10/27/using-cookie-authentication-middleware-with-web-api-and-401-response-codes/

终于得到了答案:

我的 Web 服务在我第一次请求时发送一​​个名为“dadaproaffinity”的 Cookie。此 Cookie 由 Postman 而非 Android HttpUrlConnection 自动放入以下请求。所以,我只接受这个 Cookie,现在我只用令牌在每个请求上添加这个 Cookie。

但是:这个cookie是由IIS发送的,不是我的网络服务发送的!这就是为什么它在本地工作而不在生产服务器上工作的原因。我在谷歌上搜索了这个 cookie,关于它的回复很少。我找到的唯一英文版本是:

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

是否有人有关于此 IIS Cookie 的更多信息?