.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
相关产品推荐
相关产品推荐

