You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何捕获Asp.net Core 3中Google API授权失败异常、清除Cookie并重新请求授权

解决方案:处理Google API授权失效后的重新授权流程

你的问题核心在于清除Cookie后没有正确触发重新授权流程,而且在当前请求内直接重试API调用是无效的——因为删除Cookie的操作是在响应中设置的,此时浏览器还没收到这个响应,auth.GetCredentialAsync()仍然会拿到内存中缓存的旧凭证,自然会再次抛出401错误。

下面是正确的处理方式:

步骤1:精准捕获授权失效异常并清除认证Cookie

不要删除所有Cookie,只需要删除ASP.NET Core认证系统使用的Cookie(默认名称是CookieAuthenticationDefaults.CookieName),这样更安全。同时,判断异常确实是401凭证无效的情况,避免误处理其他Google API错误。

步骤2:触发重新授权挑战

清除Cookie后,返回ChallengeResult,让ASP.NET Core的认证系统自动跳转到Google的授权页面,完成重新授权后再重定向回原页面。

修改后的控制器代码

[GoogleScopedAuthorize(PeopleServiceService.ScopeConstants.UserinfoProfile)]
public async Task<IActionResult> UserProfile([FromServices] IGoogleAuthProvider auth)
{
    try
    {
        var cred = await auth.GetCredentialAsync();
        var service = new PeopleServiceService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = cred
        });
        var request = service.People.Get("people/me");
        request.PersonFields = "names,emailAddresses";
        var person = await request.ExecuteAsync();
        return View(person);
    }
    catch (GoogleApiException e)
    {
        // 判断是否是凭证无效的401错误
        if (e.HttpStatusCode == HttpStatusCode.Unauthorized && 
            e.Error.Errors.Any(err => err.Reason == "authError"))
        {
            // 清除认证Cookie
            Response.Cookies.Delete(CookieAuthenticationDefaults.CookieName);
            
            // 触发重新授权,授权完成后重定向回当前页面
            return Challenge(
                new AuthenticationProperties { RedirectUri = Url.Action(nameof(UserProfile)) },
                GoogleOpenIdConnectDefaults.AuthenticationScheme);
        }
        
        // 其他Google API错误,抛出或自定义处理
        throw;
    }
}

为什么你的原有代码无效?

你在catch中删除Cookie后立刻重试API调用,此时:

  1. 删除Cookie的指令还在响应中,浏览器尚未接收并执行,所以客户端的Cookie还存在
  2. auth.GetCredentialAsync()会从当前请求的Cookie或内存缓存中获取旧凭证,导致再次调用API失败

必须通过ChallengeResult让用户重定向到Google授权页面,完成新的授权流程,才能获取有效的新凭证。

进阶:全局异常处理(可选)

如果多个控制器都需要处理这种情况,可以在Program.cs(.NET 6+)中配置全局异常处理中间件,统一捕获401的GoogleApiException:

// .NET 6+ Program.cs示例
app.UseExceptionHandler(errorApp =>
{
    errorApp.Run(async context =>
    {
        var exceptionHandlerPathFeature = 
            context.Features.Get<IExceptionHandlerPathFeature>();
        var exception = exceptionHandlerPathFeature?.Error;
        
        if (exception is GoogleApiException googleEx && 
            googleEx.HttpStatusCode == HttpStatusCode.Unauthorized &&
            googleEx.Error.Errors.Any(err => err.Reason == "authError"))
        {
            // 清除认证Cookie
            context.Response.Cookies.Delete(CookieAuthenticationDefaults.CookieName);
            
            // 触发重新授权
            await context.ChallengeAsync(
                GoogleOpenIdConnectDefaults.AuthenticationScheme,
                new AuthenticationProperties { RedirectUri = context.Request.Path });
        }
    });
});

这样就不用在每个控制器方法中重复编写异常处理代码了。

内容的提问来源于stack exchange,提问作者Linda Lawton - DaImTo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 12:22:39