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

.NET 6 Web API无Identity实现Google登录回调端点异常问题

解决.NET 6 Web API无Identity实现Google登录的回调跳转及Vue3捕获问题

1. 修正Google认证中间件的回调路径配置

Google OAuth认证中间件默认使用/signin-google作为回调端点,你需要显式指定自定义的回调路径,确保和Google控制台配置的一致:

builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
    // 开发环境Cookie配置,生产环境按需调整
    options.Cookie.SameSite = SameSiteMode.Lax;
    options.Cookie.SecurePolicy = CookieSecurePolicy.None;
    options.Cookie.HttpOnly = true;
})
.AddGoogle(options =>
{
    options.ClientId = builder.Configuration["Google:ClientId"];
    options.ClientSecret = builder.Configuration["Google:ClientSecret"];
    // 指定自定义回调路径,必须和Google控制台的授权重定向URI完全一致
    options.CallbackPath = "/Google/Challenge";
});

同时,Google控制台只保留http://localhost:56895/Google/Challenge这一个授权重定向URI,移除多余的signin-google,避免冲突。

2. 调整LoginController的挑战逻辑

确保Login接口正确设置回调重定向地址,Challenge接口完成认证后的用户信息处理:

[ApiController]
[Route("[controller]")]
public class LoginController : ControllerBase
{
    [HttpGet("Login")]
    public IActionResult GoogleLogin()
    {
        // 明确指定回调到自己的Challenge接口
        var redirectUri = Url.Action("Challenge", "Login");
        var authProperties = new AuthenticationProperties { RedirectUri = redirectUri };
        return Challenge(authProperties, GoogleDefaults.AuthenticationScheme);
    }

    [HttpGet("Challenge")]
    public async Task<IActionResult> GoogleChallenge()
    {
        var authResult = await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);
        if (!authResult.Succeeded)
        {
            return Unauthorized("Google认证失败");
        }

        // 提取Google返回的用户信息
        var userClaims = authResult.Principal.Claims;
        var email = userClaims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value;
        var name = userClaims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value;

        // 生成自定义JWT Token(根据你的业务需求实现)
        var jwtToken = GenerateJwtToken(email, name);

        // 针对Vue3前端,选择合适的返回方式:
        // 方式1:返回JSON,让前端直接获取Token
        return Ok(new { Token = jwtToken, Email = email });
        // 方式2:如果是弹窗登录,返回JS代码通知父窗口
        // return Content($"<script>window.opener.postMessage({{token: '{jwtToken}'}}, 'http://localhost:5173'); window.close();</script>", "text/html");
    }

    // 自定义JWT生成方法示例
    private string GenerateJwtToken(string email, string name)
    {
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Email, email),
            new Claim(ClaimTypes.Name, name)
        };

        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]));
        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

        var token = new JwtSecurityToken(
            issuer: builder.Configuration["Jwt:Issuer"],
            audience: builder.Configuration["Jwt:Audience"],
            claims: claims,
            expires: DateTime.Now.AddHours(2),
            signingCredentials: creds);

        return new JwtSecurityTokenHandler().WriteToken(token);
    }
}

3. 解决Vue3前端回调捕获问题

根据你选择的后端返回方式,调整前端逻辑:

  • 如果后端返回JSON:使用axios等工具发起请求,注意处理跨域和跳转后的回调:
    // Vue组件中的登录方法
    const handleGoogleLogin = async () => {
      try {
        // 直接跳转后端登录接口,授权完成后会回调到Challenge接口返回Token
        window.location.href = 'http://localhost:56895/Login/Login';
        // 或者用弹窗方式,监听返回
        const loginWindow = window.open('http://localhost:56895/Login/Login', '_blank', 'width=600,height=600');
        window.addEventListener('message', (event) => {
          if (event.origin === 'http://localhost:56895') {
            const { token } = event.data;
            localStorage.setItem('token', token);
            loginWindow.close();
            // 跳转到首页或更新用户状态
            router.push('/');
          }
        });
      } catch (err) {
        console.error('登录失败', err);
      }
    };
    
  • 配置Vue路由:如果后端重定向到前端,需要在Vue Router中添加对应路由处理回调:
    const routes = [
      // 其他路由
      {
        path: '/google-callback',
        component: GoogleCallbackComponent,
        props: route => ({ token: route.query.token })
      }
    ];
    

4. 检查跨域(CORS)配置

确保后端允许Vue3前端的跨域请求,在Program.cs中添加:

builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowVueApp", policy =>
    {
        policy.WithOrigins("http://localhost:5173") // Vue3默认端口
              .AllowAnyHeader()
              .AllowAnyMethod()
              .AllowCredentials(); // 允许携带Cookie,认证需要
    });
});

// 注意中间件顺序:UseCors要在UseAuthentication和UseAuthorization之前
app.UseCors("AllowVueApp");
app.UseAuthentication();
app.UseAuthorization();

内容的提问来源于stack exchange,提问作者An Ku

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 00:01:12