在开发机器上运行本地时一切正常。但是当CI部署到开发服务器时,我们会遇到以下问题。
网站正确重定向到登录,登录成功后,我被重定向回客户端回调页面,该页面更新状态,然后尝试通过userManager.getUser()
加载用户
这导致以下结果:
无法加载https://dev-auth.mysite.com/connect/userinfo:对预检请求的响应未通过访问控制检查:否' Access-Control-Allow-Origin'标头出现在请求的资源上。起源' https://dev-spa.mysite.com'因此不允许访问。响应的HTTP状态代码为404.
从Seq Serilog我们看到以下其他呼叫成功。
请求启动HTTP / 1.1 GET http://dev-auth.mysite.com/.well-known/openid-configuration/jwks 请求启动HTTP / 1.1 GET http://dev-auth.mysite.com/.well-known/openid-configuration 请求启动HTTP / 1.1 GET http://dev-auth.mysite.com/connect/authorize/callback?client_id= ... 请求启动HTTP / 1.1 POST http://dev-auth.mysite.com/Account/Login application / x-www-form-urlencoded 643 请求启动HTTP / 1.1 GET http://dev-auth.mysite.com/account/login?returnUrl= ... 请求启动HTTP / 1.1 GET http://dev-auth.mysite.com/connect/authorize?client_id= ... 请求启动HTTP / 1.1 GET http://dev-auth.mysite.com/.well-known/openid-configuration
项目是:
所有项目都是.net core 2.0。 spa项目提供使用oidc-client软件包的react应用程序。
Startup的CofigureServices for Identity服务器部分是:
public void ConfigureServices(IServiceCollection aServiceCollection)
{
// CorsPolicy.Any.Apply(aServiceCollection);
aServiceCollection.AddMvc();
//aServiceCollection.AddMvcCore()
// .AddJsonFormatters()
// .AddRazorViewEngine();
aServiceCollection.AddSession();
ConfigureServicesIdentityServer(aServiceCollection);
aServiceCollection.Configure<RazorViewEngineOptions>(options =>
{
options.ViewLocationExpanders.Add(new ViewLocationExpander());
});
aServiceCollection.AddMediatR();
}
private static void ConfigureServicesIdentityServer(IServiceCollection aServiceCollection)
{
aServiceCollection.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryApiResources(Resources.GetApiResources())
.AddInMemoryClients(Clients.GetClients())
.AddInMemoryIdentityResources(Resources.GetIdentityResources())
// .AddJwtBearerClientAuthentication();
}
配置
public void Configure(
IApplicationBuilder aApplicationBuilder,
IHostingEnvironment aHostingEnvironment,
IOptions<RequestLocalizationOptions> aRequestLocalizationOptions)
{
Environment.UseExceptionPage(aHostingEnvironment, aApplicationBuilder);
// aApplicationBuilder.UseCors(CorsPolicy.Any.DisplayName);
aApplicationBuilder.UseIdentityServer();
aApplicationBuilder.UseRequestLocalization(aRequestLocalizationOptions.Value);
aApplicationBuilder.UseStaticFiles(); // Serve up static files from wwwroot images etc...
aApplicationBuilder.UseSession();
aApplicationBuilder.UseMvc();
}
客户端配置:
new Client
{
ClientId = "someGUID",
ClientName = "MySite",
RequireClientSecret=false, // if false this is a public client.
AllowedGrantTypes = GrantTypes.Implicit,
AllowAccessTokensViaBrowser = true,
AlwaysIncludeUserClaimsInIdToken = true,
RedirectUris = {
"http://local-spa.mysite.com:3000/callback",
"https://dev-spa.mysite.com/callback",
},
PostLogoutRedirectUris = {
"http://local-spa.mysite.com:3000/",
"https://dev-spa.mysite.com/",
},
AllowedCorsOrigins = {
"http://local-spa.mysite.com:3000",
"https://dev-spa.mysite.com",
},
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
IdentityServerConstants.StandardScopes.Phone,
Resources.WebOrderingApi,
},
RequireConsent = false,
},
TypeScript客户端:
import { Log, OidcClientSettings, UserManager, UserManagerSettings, } from 'oidc-client';
...
const protocol: string = window.location.protocol;
const hostname: string = window.location.hostname;
const port: string = window.location.port;
const oidcClientSettings: OidcClientSettings = {
client_id: '46a0ab4a-1321-4d77-abe5-98f09310df0b',
post_logout_redirect_uri: `${protocol}//${hostname}${port ? `:${port}` : ''}/`,
redirect_uri: `${protocol}//${hostname}${port ? `:${port}` : ''}/callback`,
response_type: 'id_token token',
scope: 'openid profile email phone WebOrderingApi',
};
const userManagerSettings: UserManagerSettings = {
...oidcClientSettings,
automaticSilentRenew: false,
filterProtocolClaims: true,
loadUserInfo: true,
monitorSession: false,
silent_redirect_uri: `${protocol}//${hostname}${port ? `:${port}` : ''}/callback`,
};
事实证明,开发IIS服务器不允许使用OPTIONS动词。这是在不需要CORS的生产服务器中建议做的事情,但我不建议将其用于开发环境。
感谢所有人的贡献。
答案 0 :(得分:1)
对预检请求的响应没有通过访问控制检查:否&#39;访问控制 - 允许 - 来源&#39;标头出现在请求的资源上。起源&#39; https://dev-spa.mysite.com&#39;因此不允许访问。响应的HTTP状态代码为404.
在发出请求之前,会发出CORS请求,以检查是否应该允许该请求,这是使用OPTIONS方法发送的,服务器使用404响应,停止请求
您需要发回有效的OPTIONS响应,允许请求。
我建议使用Wireshark或其他一些检查器查看发送的请求及其响应,以帮助调试CORS响应停止请求的原因。
正如@Kirk提到above,问题可能是HTTPS,无论是使用CORS请求,还是整个服务器都不支持HTTPS。
答案 1 :(得分:1)
从错误消息中,我在最后注意到以下内容:
响应的HTTP状态代码为404.
这表明您的问题实际上可能不是CORS问题 - 可能更多的是找不到您尝试访问的端点,从而导致404响应。当然,此404响应不太可能包含相关的Access-Control-Allow-Origin
标题。
查看您的日志,所有成功拨打dev-auth.mysite.com
的电话都使用http
方案。但是,在引用connect/userinfo
端点时,您的错误消息引用了https
方案:
无法加载 https ://dev-auth.mysite.com/connect/userinfo
答案 2 :(得分:0)
此问题的一个解决方法是允许IIS中的OPTIONS谓词用于auth服务器。
答案 3 :(得分:0)
根据文档,您可以在.NET Core CORS中混合使用,IdentityServer将兑现它。在您的Startup.cs中,添加:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddCors(options =>
{
options.AddPolicy("WhateverNameYouWantHere",
builder =>
{
builder.WithOrigins($"http://{_frontendUri}",
$"https://{_frontendUri}")
.AllowCredentials()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
...
}
然后再
public void Configure(IApplicationBuilder app)
{
...
app.UseCors("WhateverNameYouWantHere");
}