.NET Core 6.0 Google登录时ClaimsPrincipal.Identities返回null问题
问题分析与修复方案
核心问题
- 中间件配置缺失与顺序错误:你的Program.cs中未添加
app.UseAuthentication()中间件,且UseSession的位置不符合ASP.NET Core中间件执行顺序要求,导致认证流程无法正常触发。 - 回调方法逻辑错误:在
GoogleLoginProc中,你直接尝试通过Cookie认证方案获取用户信息,但此时Google OAuth回调后的用户身份还未被保存到Cookie中,因此result.Principal为null,进而引发Identities空引用错误。
修复步骤
1. 修正Program.cs中间件配置
调整中间件顺序并添加认证中间件:
using Microsoft.AspNetCore.Authentication.Cookies; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllersWithViews(); builder.Services.AddSession(options => { options.IdleTimeout = TimeSpan.FromSeconds(10); options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; }); builder.Services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; }) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => { options.Cookie.Name = ".Cookies.NetCoreSocialLogin"; options.LoginPath = new PathString("/account/login"); options.LogoutPath = new PathString("/account/logout"); options.AccessDeniedPath = new PathString("/error/403"); }) .AddGoogle(options => { options.CallbackPath = "/account/signin-google"; options.ClientId = "你的ClientId"; options.ClientSecret = "你的ClientSecret"; }); var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseSession(); // 调整到路由中间件之前 app.UseRouting(); app.UseAuthentication(); // 添加认证中间件,必须在授权中间件之前 app.UseAuthorization(); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run();
2. 修正AccountController的回调方法逻辑
修改GoogleLoginProc,先获取Google OAuth的认证结果,再将用户身份保存到Cookie中:
using netcore_social_login.Dtos; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.Google; using Microsoft.AspNetCore.Mvc; namespace netcore_social_login.Controllers { [Route("account")] public class AccountController : Controller { [HttpGet("login")] public IActionResult GoogleLogin() { var properties = new AuthenticationProperties { RedirectUri = Url.Action("GoogleLoginProc") }; return Challenge(properties, GoogleDefaults.AuthenticationScheme); } [HttpGet("signin-google")] public async Task<IActionResult> GoogleLoginProc() { // 先获取Google OAuth的认证结果 var result = await HttpContext.AuthenticateAsync(GoogleDefaults.AuthenticationScheme); if (!result.Succeeded) { // 认证失败时跳转回登录页 return RedirectToAction("Login"); } // 提取Google返回的身份信息 var googleIdentity = result.Principal.Identities.FirstOrDefault(); if (googleIdentity == null) { return RedirectToAction("Login"); } var claims = googleIdentity.Claims.Select(claim => new ClaimJson { Issuer = claim.Issuer, OriginalIssuer = claim.OriginalIssuer, Type = claim.Type, Value = claim.Value, ValueType = claim.ValueType }).ToList(); var providerKey = claims .Where(x => x.Type.Equals("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier")) .Select(x => x.Value) .FirstOrDefault(); var emailAddress = claims .Where(x => x.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress") .Select(x => x.Value) .FirstOrDefault(); // 创建Cookie认证所需的身份信息 var claimsIdentity = new ClaimsIdentity(googleIdentity.Claims, CookieAuthenticationDefaults.AuthenticationScheme); var authProperties = new AuthenticationProperties { IsPersistent = false // 根据需求设置是否持久化登录 }; // 将用户身份保存到Cookie中,后续请求可通过Cookie获取用户信息 await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), authProperties); return RedirectToAction("Index", "Home"); } } }
关键说明
- 中间件顺序必须严格遵循:静态文件 → Session → 路由 → 认证 → 授权,否则认证流程会失效。
- 回调方法中需先通过Google认证方案获取用户信息,再将其转换为Cookie认证的身份,这样后续请求才能通过Cookie正常获取用户Principal。
内容的提问来源于stack exchange,提问作者sangeun jo
相关产品推荐
相关产品推荐

