如何在ASP.NET Core 6 Web API中将Google外部登录写入Identity表
ASP.NET Core Identity 提供了完整的内置能力实现这个需求,不需要手动编写SQL操作Users、UserLogins、UserClaims等表。网上MVC场景的教程核心逻辑完全适用于WebAPI,唯一区别是WebAPI不需要处理视图渲染、浏览器重定向逻辑,所有接口直接返回JSON结果即可。
具体实现步骤
1. 安装依赖并配置服务
首先确保项目引入以下NuGet包:
Microsoft.AspNetCore.Authentication.JwtBearerMicrosoft.AspNetCore.Identity.EntityFrameworkCoreMicrosoft.AspNetCore.Authentication.Google
在Program.cs中注册服务,注意和MVC场景的核心差异是不要将Cookie认证作为默认方案,避免未认证时触发302跳转:
// 注册Identity服务,和你原有本地账号登录的配置保持一致即可 builder.Services.AddIdentity<IdentityUser, IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultTokenProviders(); // 配置JWT为API默认认证方案 builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(/* 保留你原有校验系统自有JWT的配置 */) .AddGoogle(googleOptions => { googleOptions.ClientId = builder.Configuration["Authentication:Google:ClientId"]; googleOptions.ClientSecret = builder.Configuration["Authentication:Google:ClientSecret"]; // 关键配置:指定外部登录结果的临时存储方案,禁止自动触发浏览器跳转 googleOptions.SignInScheme = IdentityConstants.ExternalScheme; });
2. 编写Google登录接口
前端通过Google SDK拿到id_token后,直接POST给后端接口,接口内完全使用Identity内置方法完成逻辑,不需要手动操作数据库:
[ApiController] [Route("api/auth")] public class AuthController : ControllerBase { private readonly UserManager<IdentityUser> _userManager; private readonly SignInManager<IdentityUser> _signInManager; public AuthController(UserManager<IdentityUser> userManager, SignInManager<IdentityUser> signInManager) { _userManager = userManager; _signInManager = signInManager; } [HttpPost("google-login")] public async Task<IActionResult> GoogleLogin([FromBody] GoogleLoginRequest request) { // 内置方法自动校验Google JWT合法性,解析出Google返回的用户身份信息 var externalLoginInfo = await _signInManager.GetExternalLoginInfoAsync( loginProvider: "Google", providerKey: null, authenticationToken: request.GoogleIdToken); if (externalLoginInfo == null) { return BadRequest("Google令牌校验失败,请重新登录"); } // 查询系统内是否已存在绑定该Google账号的用户 var existingUser = await _userManager.FindByLoginAsync(externalLoginInfo.LoginProvider, externalLoginInfo.ProviderKey); bool isNewUser = false; if (existingUser == null) { isNewUser = true; // 从Google返回的身份信息中提取邮箱作为新用户账号 var email = externalLoginInfo.Principal.FindFirstValue(ClaimTypes.Email); var newUser = new IdentityUser { UserName = email, Email = email, EmailConfirmed = true // Google已完成邮箱验证,直接标记为已确认 }; // 内置方法创建用户,自动写入Users表 var createUserResult = await _userManager.CreateAsync(newUser); if (!createUserResult.Succeeded) { return BadRequest(createUserResult.Errors); } // 内置方法关联Google登录信息,自动写入UserLogins表 var addLoginResult = await _userManager.AddLoginAsync(newUser, externalLoginInfo); if (!addLoginResult.Succeeded) { return BadRequest(addLoginResult.Errors); } // 如需存储Google返回的姓名、头像等信息,用内置方法写入UserClaims表 var requiredClaims = externalLoginInfo.Principal.Claims.Where(c => c.Type is ClaimTypes.Name or ClaimTypes.GivenName or "picture" ); await _userManager.AddClaimsAsync(newUser, requiredClaims); existingUser = newUser; } // 执行登录逻辑,生成系统自有JWT返回给前端 await _signInManager.SignInAsync(existingUser, isPersistent: false); var appToken = GenerateYourOwnJwtToken(existingUser); // 替换为你项目原有的JWT生成逻辑 return Ok(new { AccessToken = appToken, IsNewUser = isNewUser, UserName = existingUser.UserName }); } } public class GoogleLoginRequest { public string GoogleIdToken { get; set; } }
注意事项
- 所有用到的
GetExternalLoginInfoAsync、CreateAsync、AddLoginAsync、AddClaimsAsync都是Identity的内置方法,会自动维护各张Identity表的关联关系和字段约束,和MVC场景调用的方法完全一致。 - 前端集成Google SDK时,必须申请
openid、email、profile权限,否则后端拿不到邮箱、姓名等必要的用户信息。 - 如果需要扩展用户字段(比如增加头像、用户等级字段),只要将代码中的
IdentityUser替换为你自定义的继承自IdentityUser的用户类即可,其他逻辑不需要调整。 - 不要去掉
googleOptions.SignInScheme = IdentityConstants.ExternalScheme配置,否则接口在校验失败时会返回302重定向响应,不符合WebAPI的返回规范。
内容的提问来源于stack exchange,提问作者CSharp-n
相关产品推荐
相关产品推荐

