kiw*_*hen 5 ajax cors identityserver3
我目前正在使用各种 Ajax 请求来保存、加载和自动完成数据的站点上工作。它是使用 C#、MVC 和 JQuery 构建的。MVC 控制器上的所有操作都需要用户获得授权,我们使用 IdentityServer3 进行身份验证。它是使用 NuGet 安装的,当前版本为 2.3.0。
当我打开页面并按下按钮时,一切正常。当某个会话过期时,似乎会出现该问题。如果我闲置一段时间并尝试使用 Ajax 函数,则会生成以下错误:
XMLHttpRequest 无法加载https://identityserver.domain.com/connect/authorize?client_id=Bar&redirect_uri=http%3a%2f%2flocalhost%3a12345&response_mode=form_post&response_type=id_token+token&scope=openid+profile+email+phone+roles [... ]。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,不允许访问Origin ' http://localhost:12345 '。
根据我对 Ajax 的了解,问题本身非常简单。MVC 站点已丢失对当前会话的跟踪,并要求客户端再次进行身份验证。我从 Ajax 请求中得到的响应是“302 Found”,带有指向我们的 IdentityServer 的位置标头。IdentityServer 恰好在另一个域中,虽然这在您执行常规 HTTP 请求时可以正常工作,但对于 Ajax 请求却不是特别好。“同源策略”直接阻止了 Ajax 功能的身份验证。如果我刷新页面,我将被重定向到 IdentityServer 并正常进行身份验证。然后事情会在几分钟内恢复正常。
解决方案可能是在来自 IdentityServer 的响应消息中添加一个额外的标头,明确指出该服务允许跨域请求。
我目前没有从 IdentityServer 获得这个标头(在 Fiddler 中检查)。
根据 docs,它应该默认启用。我已经检查过我们确实以这种方式启用了 CORS:
factory.CorsPolicyService = new Registration<ICorsPolicyService>(new DefaultCorsPolicyService { AllowAll = true });
Run Code Online (Sandbox Code Playgroud)
这是我的一位客户:
new Client
{
Enabled = true,
ClientName = "Foo",
ClientId = "Bar",
ClientSecrets = new List<Secret>
{
new Secret("Cosmic")
},
Flow = Flows.Implicit,
RequireConsent = false,
AllowRememberConsent = true,
AccessTokenType = AccessTokenType.Jwt,
PostLogoutRedirectUris = new List<string>
{
"http://localhost:12345/",
"https://my.domain.com"
},
RedirectUris = new List<string>
{
"http://localhost:12345/",
"https://my.domain.com"
},
AllowAccessToAllScopes = true
}
Run Code Online (Sandbox Code Playgroud)
这些设置不起作用。我注意到这里的 URI 中有一个额外的正斜杠,但是如果我删除它们,我会得到默认的 IdentityServer 错误,指出客户端未经授权(错误的 URI)。如果我部署站点(而不是运行本地主机调试),我会使用没有尾部斜杠的域名,并且我得到与调试完全相同的行为。我确实注意到上面的错误消息中没有尾部斜杠,我认为这可能是问题所在,直到我在站点的部署版本中看到相同的内容。
我还制作了自己的政策提供者,如下所示:
public class MyCorsPolicyService : ICorsPolicyService
{
public Task<bool> IsOriginAllowedAsync(string origin)
{
return Task.FromResult(true);
}
}
Run Code Online (Sandbox Code Playgroud)
...我将它插入到 IdentityServerServiceFactory 中,如下所示:
factory.CorsPolicyService = new Registration<ICorsPolicyService>(new MyCorsPolicyService());
Run Code Online (Sandbox Code Playgroud)
这个想法是让它无论来源如何都返回真。这也不起作用;与之前的结果完全相同。
我已经阅读了关于这个特定主题的十几个其他主题,但我一无所获。据我所知,在设置不同站点时,我们并没有做任何不寻常的事情。这几乎都是开箱即用的。有什么建议吗?
问题仍然存在。我现在尝试了一些新的策略。我在某处读到 cookie 身份验证对 Ajax 请求不利,我应该改用不记名令牌。我在 Ajax 中这样设置:
$(function () {
$(document).ajaxSend(function (event, request, settings) {
console.log("Setting bearer token.");
request.setRequestHeader("Authorization", "Bearer " + $bearerToken);
});
});
Run Code Online (Sandbox Code Playgroud)
Chrome 和 Fiddler 中的控制台都确认令牌确实存在并由 JQuery 发送。我使用的令牌来自 HttpContext.GetOwinContext().Authentication.User 的声明主体对象上的 access_token-property。
这没有多大作用。我仍然收到来自服务器的 302 响应,并且 Fiddler 显示令牌未通过以下 Ajax 请求(这是一个 GET 请求)发送到 IdentityServer。
从那里,我读到了这个线程: 处理对 ASP.NET MVC 操作的 CORS 预检请求 我试图将此代码放入 IdentityServer 的 startup.cs 中,但似乎没有进入“预检”请求。所有我在 Fiddler 中看到的是这个(从一开始):
POST http://localhost:12345/my/url HTTP/1.1
Host: localhost:12345
Connection: keep-alive
Content-Length: pretty long
Authorization: Bearer <insert long token here>
Origin: http://localhost:12345
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
Referer: http://localhost:12345/my/url
Accept-Encoding: gzip, deflate
Accept-Language: nb-NO,nb;q=0.8,no;q=0.6,nn;q=0.4,en-US;q=0.2,en;q=0.2
Cookie: OpenIdConnect.nonce.<insert 30 000 lbs of hashed text here>
param=fish&morestuff=salmon&crossDomain=true
Run Code Online (Sandbox Code Playgroud)
HTTP/1.1 302 Found
Cache-Control: private
Location: https://identityserver.domain.com/connect/authorize?client_id=Bar&redirect_uri=http%3a%2f%2flocalhost%3a12345%2f&response_mode=form_post&response_type=id_token+token&scope=openid+profile+email [...]
Server: Microsoft-IIS/10.0
X-AspNetMvc-Version: 5.2
X-AspNet-Version: 4.0.30319
Set-Cookie: OpenIdConnect.nonce.<lots of hashed text>
X-SourceFiles: <more hashed text>
X-Powered-By: ASP.NET
Date: Fri, 15 Jan 2016 12:23:08 GMT
Content-Length: 0
Run Code Online (Sandbox Code Playgroud)
GET https://identityserver.domain.com/connect/authorize?client_id=Bar&redirect_uri=http%3a%2f%2flocalhost%3a12345%2f&response_mode=form_post&response_type=id_token+token&scope=openid+profile+email [...]
Host: identityserver.domain.com
Connection: keep-alive
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://localhost:12345
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://localhost:12345/my/url
Accept-Encoding: gzip, deflate, sdch
Accept-Language: nb-NO,nb;q=0.8,no;q=0.6,nn;q=0.4,en-US;q=0.2,en;q=0.2
Run Code Online (Sandbox Code Playgroud)
HTTP/1.1 302 Found
Content-Length: 0
Location: https://identityserver.domain.com/login?signin=<some hexadecimal id>
Server: Microsoft-IIS/8.5
Set-Cookie: SignInMessage.<many, many, many hashed bytes>; path=/; secure; HttpOnly
X-Powered-By: ASP.NET
Date: Fri, 15 Jan 2016 12:23:11 GMT
Run Code Online (Sandbox Code Playgroud)
XMLHttpRequest 无法加载https://identityserver.domain.com/connect/authorize?client_id=Bar&blahblahblah。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,不允许访问Origin ' http://localhost:12345 '。
我也遇到了这个问题,但UseTokenLifetime = false没有解决问题,因为你失去了 STS 上的令牌有效性。
当我尝试访问授权的 api 方法时,即使我在 Owin 上有效,我仍然得到 401。
我找到的解决方案是保留UseTokenLifetime = true默认值,但编写一个全局ajax错误处理程序(或角度http拦截器),如下所示:
$.ajaxSetup({
global: true,
error: function(xhr, status, err) {
if (xhr.status == -1) {
alert("You were idle too long, redirecting to STS") //or something like that
window.location.reload();
}
}});
Run Code Online (Sandbox Code Playgroud)
触发身份验证工作流程。
| 归档时间: |
|
| 查看次数: |
4423 次 |
| 最近记录: |