当 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
我尝试过的:
- 在本地重现此错误:它在来自 android 应用程序或来自 Postman
的本地服务器(Web 和 SQL 服务器)上运行良好
- 我检查令牌是否在每个请求中都正确发送
- 来自Android的请求每次都一样
- 试图将缺失的 header 添加到我的 android 应用程序请求中
我在这个问题上花了两天时间,阅读了很多 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 的更多信息?
我正在开发一个 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
我尝试过的:
- 在本地重现此错误:它在来自 android 应用程序或来自 Postman 的本地服务器(Web 和 SQL 服务器)上运行良好
- 我检查令牌是否在每个请求中都正确发送
- 来自Android的请求每次都一样
- 试图将缺失的 header 添加到我的 android 应用程序请求中
我在这个问题上花了两天时间,阅读了很多 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 的更多信息?