【发布时间】:2018-02-18 08:44:28
【问题描述】:
我正在尝试使用 ASP.NET 中间件通过 Google OAuth 进行身份验证。我了解我遇到的问题是由 CORS 问题引起的,但我似乎无法解决这些问题。
我的启动类配置如下:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder
.AllowAnyHeader()
.AllowAnyMethod()
.AllowAnyOrigin()
.AllowCredentials()
);
......
services.AddGoogle(o =>
{
o.ClientId = Configuration["Authentication:Google:ClientId"];
o.ClientSecret = Configuration["Authentication:Google:ClientSecret"];
o.AuthorizationEndpoint += "?prompt=consent"; // Hack so we always get a refresh token, it only comes on the first authorization response
o.AccessType = "offline";
o.SaveTokens = true;
o.Events = new OAuthEvents()
{
OnRemoteFailure = ctx =>
{
ctx.Response.Redirect("/error?FailureMessage=" + UrlEncoder.Default.Encode(ctx.Failure.Message));
ctx.HandleResponse();
return Task.FromResult(0);
}
};
o.ClaimActions.MapJsonSubKey("urn:google:image", "image", "url");
o.ClaimActions.Remove(ClaimTypes.GivenName);
});
...........
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole();
//if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors("CorsPolicy");
app.Use(async (context, next) =>
{
await next();
// Serve index file and allow Angular to take over routing if (NotFound)
if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value))
{
context.Request.Path = "/index.html";
await next();
}
});
app.UseAuthentication();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseMvc();
}
在我的身份验证控制器中:
// POST: api/auth/ExternalLogin
[HttpPost("loginexternal")]
[AllowAnonymous]
public async Task<IActionResult> LoginExternal([FromBody]string provider)
{
// Clear the existing external cookie to ensure a clean login process
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
// Request a redirect to the external login provider to link a login for the current user
var redirectUrl = Url.Action(nameof(ExternalLoginCallback));
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, _userManager.GetUserId(User));
return new ChallengeResult(provider, properties);
}
调用此函数的我的打字稿角代码:
loginExternal() {
const headers = new HttpHeaders({ 'Content-Type': 'application/json', 'Accept': 'application/json' });
return this.http.post(this.baseUrl + '/auth/loginexternal', '"Google"', { headers: headers })
.map((res: any) => {
localStorage.setItem('auth_token', res.auth_token);
this.loggedIn = true;
this._authNavStatusSource.next(true);
return true;
})
.catch(this.handleError);
}
这就是响应
在我的 LoginExternal 操作中执行 ChallengeResult 后发生上述响应。
【问题讨论】:
-
您的代码正在尝试将 JSON 数据跨域发布到
https://accounts.google.com/o/oauth2/auth,这会导致您的浏览器首先向https://accounts.google.com/o/oauth2/auth发送 CORS 预检 OPTIONS 请求以询问是否可以获取该跨域邮政。而https://accounts.google.com/o/oauth2/auth正在响应告诉浏览器,Nope。所以浏览器就停在那里,从不尝试你的 POST 请求。 …无论如何,你无法“解决”这个问题——你的代码正在尝试做https://accounts.google.com明确不希望你做的事情。 -
ASP.NET 中间件正在通过控制器执行该请求,不是吗?我的 post 方法只发送到我的控制器。
-
不,您的前端代码正在尝试执行该 POST 请求。如果它是 ASP.NET 中间件,它就可以工作——因为 ASP.NET 中间件不会强制执行同源策略并强制执行跨域限制。浏览器可以。这就是为什么是您的浏览器向您显示 CORS 错误消息的原因。
-
那么为什么在使用默认的 ASP.NET MVC 模板和视图中提取身份验证代码时,这段代码可以工作?抱歉,我正在尝试找到解决方法...单步执行调试器时,post 方法会命中我的控制器,该错误仅在中间件 ChellengeResult 方法执行后发生。
-
这有什么更新吗?我也遇到了同样的问题。
标签: angular authentication asp.net-core cors