.NET 8 Web应用中如何重写signin-google端点获取Google访问令牌
如何在.NET 8中自定义Google外部登录回调逻辑(替代默认/signin-google端点)
默认情况下,ASP.NET Core OAuth中间件会优先处理Google登录的/signin-google回调端点,直接用控制器路由覆盖这个端点无效,暴力映射端点又会破坏其他登录流程,这里提供两种合规的解决方案:
方案一:利用OAuth事件拦截令牌(推荐)
无需修改默认回调端点,通过中间件的事件机制在回调流程中插入自定义逻辑,获取授权码或访问令牌:
在配置Google认证时添加事件处理:
builder.Services.AddAuthentication() .AddGoogle(options => { options.ClientId = builder.Configuration["Authentication:Google:ClientId"]; options.ClientSecret = builder.Configuration["Authentication:Google:ClientSecret"]; options.Events = new OAuthEvents { // 在令牌接收阶段获取授权码 OnTokenReceived = async context => { var authorizationCode = context.TokenEndpointRequest.Code; // 调用业务服务保存授权码 await context.HttpContext.RequestServices .GetRequiredService<ILoginService>() .RegisterTokenAsync(context.Principal?.Identity?.Name, authorizationCode); }, // 在用户票据创建阶段,可获取完整用户身份和访问令牌 OnCreatingTicket = async context => { var userName = context.Principal.Identity.Name; var accessToken = context.AccessToken; // 保存访问令牌到业务系统 await context.HttpContext.RequestServices .GetRequiredService<ILoginService>() .RegisterTokenAsync(userName, accessToken); } }; });
这种方式复用中间件默认流程,不会影响其他登录方式,同时能轻松获取所需令牌信息。
方案二:自定义回调端点
如果需要完全掌控回调流程,可以修改Google认证的CallbackPath,将回调指向自定义控制器端点:
1. 修改Google认证配置
builder.Services.AddAuthentication() .AddGoogle(options => { options.ClientId = builder.Configuration["Authentication:Google:ClientId"]; options.ClientSecret = builder.Configuration["Authentication:Google:ClientSecret"]; // 将回调路径改为自定义端点 options.CallbackPath = "/account/google-callback"; });
2. 实现自定义回调控制器方法
public class AccountController : Controller { private readonly ILoginService _loginService; private readonly IAuthenticationService _authService; public AccountController(ILoginService loginService, IAuthenticationService authService) { _loginService = loginService; _authService = authService; } [HttpGet("/account/google-callback")] public async Task<IActionResult> GoogleCallback() { // 让认证中间件处理回调请求,生成用户身份 var authResult = await _authService.AuthenticateAsync(HttpContext, GoogleDefaults.AuthenticationScheme); if (authResult.Succeeded) { // 从认证属性中提取授权码和访问令牌 var authProps = authResult.Properties; var code = authProps.GetTokenValue("code"); var accessToken = authProps.GetTokenValue("access_token"); // 保存令牌到业务系统 await _loginService.RegisterTokenAsync(authResult.Principal.Identity.Name, code); // 完成用户登录 await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, authResult.Principal, authProps); return RedirectToAction("Index", "Home"); } return RedirectToAction("Login", "Account"); } }
为什么之前的方法无效?
- 直接用
[Route("signin-google")]标注控制器方法无效:OAuth中间件会在端点路由之前匹配CallbackPath对应的请求,控制器路由根本不会被命中。 - 暴力映射端点会覆盖中间件的处理逻辑,导致依赖中间件的其他登录方式(如用户名密码登录)失效。
内容的提问来源于stack exchange,提问作者PointlessSpike
相关产品推荐
相关产品推荐

