使用 Google Auth、Angular 4、ASP.Net Core 2 进行身份验证时出现 405

Posted

技术标签:

【中文标题】使用 Google Auth、Angular 4、ASP.Net Core 2 进行身份验证时出现 405【英文标题】:405 when authenticating using Google Auth, Angular 4, ASP.Net Core 2 【发布时间】: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 方法执行后发生。 这有什么更新吗?我也遇到了同样的问题。 【参考方案1】:

尝试使用 this.document.location.href 甚至 window.location.href 重定向到您的 google 身份验证页面,而不是向您的 .net 核心控制器操作发出 http 请求。

@Injectable()
export class LoginService 
    //...

    constructor(@Inject(DOCUMENT) private document: Document,...)

    login() 
        this.document.location.href 'https://www.mywebsite.com/account/signInWithGoogle';
    

这是控制器动作中的样子:

public class AccountController : Controller

    private readonly SignInManager<IdentityUser> _signInManager;
    private readonly UserManager<IdentityUser> _userManager;
    public AccountController(SignInManager<IdentityUser> signInManager, UserManager<IdentityUser> userManager)
    
        _signInManager = signInManager;
        _userManager = userManager;
    

    public IActionResult SignInWithGoogle()
    
        var authenticationProperties = _signInManager.ConfigureExternalAuthenticationProperties("Google", Url.Action(nameof(HandleExternalLogin)));
        return Challenge(authenticationProperties, "Google");
    

    ...

向导:https://www.blinkingcaret.com/2018/10/10/sign-in-with-an-external-login-provider-in-an-angular-application-served-by-asp-net-core/

【讨论】:

以上是关于使用 Google Auth、Angular 4、ASP.Net Core 2 进行身份验证时出现 405的主要内容,如果未能解决你的问题,请参考以下文章

Laravel Rest API Google Auth 在 Angular

django-rest-auth + django-allauth + angular2

允许用户在使用angular firebase与google注册时,选择用哪个邮箱注册。

.NET Core 2 WebAPI CORS 与 Angular 4 前端和 Windows Auth 的问题

无法从另一个组件/ Angular 4中的auth.service访问错误消息

谷歌在 Angular 7 中使用 .NET Core API 登录