Asp.net Core 2.0外部认证用户身份无法跨请求持久化问题
解决Asp.Net Core 2.0外部认证后身份跨请求丢失的问题
看起来你已经搭好了外部认证的基础框架,但核心问题在于外部认证成功后,没有把外部身份和本地系统的用户身份关联起来,也没完成登录流程,导致后续请求无法识别用户身份。下面分步骤帮你解决:
1. 先检查Configure方法是否启用认证中间件
首先确认你的Configure方法里,是否在UseMvc之前添加了UseAuthentication——这是很多人容易忽略的点,没加的话认证中间件根本不会处理后续请求的身份:
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { // 其他中间件(比如UseStaticFiles、UseDeveloperExceptionPage等) app.UseAuthentication(); // 这行必须放在UseMvc前面 app.UseMvc(); }
2. 完善OnTicketReceived事件,完成本地用户关联与登录
你的HandleOnTicketReceived只拿到了外部身份,但没有把它转换成本地系统的用户身份,也没触发登录动作。需要借助SignInManager<IdentityUser>和UserManager<IdentityUser>来完成这个流程:
第一步:在Startup中注入必要服务
先把需要的服务注入到Startup构造函数,方便在事件中调用:
private readonly IAuthService _authService; private readonly SignInManager<IdentityUser> _signInManager; private readonly UserManager<IdentityUser> _userManager; public Startup(IConfiguration configuration, IAuthService authService, SignInManager<IdentityUser> signInManager, UserManager<IdentityUser> userManager) { Configuration = configuration; _authService = authService; _signInManager = signInManager; _userManager = userManager; } // 然后在AddGoogle/AddTwitter的Events中使用这些实例 services.AddAuthentication() .AddGoogle(googleOptions => { // ... 原有配置 googleOptions.Events = new OAuthEvents { OnTicketReceived = async e => await HandleOnTicketReceived(e), }; });
第二步:更新HandleOnTicketReceived方法逻辑
在这个方法里,我们要根据外部登录信息查找已有用户,没有的话就创建新用户,最后完成登录:
private async Task HandleOnTicketReceived(TicketReceivedContext e) { var externalLoginInfo = await _signInManager.GetExternalLoginInfoAsync(); if (externalLoginInfo == null) { e.Response.Redirect("/Account/Login"); e.HandleResponse(); return; } // 尝试用外部登录信息登录已有用户 var signInResult = await _signInManager.ExternalLoginSignInAsync( externalLoginInfo.LoginProvider, externalLoginInfo.ProviderKey, isPersistent: true, bypassTwoFactor: true); if (signInResult.Succeeded) { // 已有关联用户,直接完成流程 return; } else { // 创建新的本地用户 var email = externalLoginInfo.Principal.FindFirstValue(ClaimTypes.Email); var user = new IdentityUser { UserName = email, Email = email }; var createResult = await _userManager.CreateAsync(user); if (createResult.Succeeded) { // 将外部登录与新用户关联 createResult = await _userManager.AddLoginAsync(user, externalLoginInfo); if (createResult.Succeeded) { // 登录新创建的用户 await _signInManager.SignInAsync(user, isPersistent: true); } } // 如果创建/关联失败,跳转到错误页 if (!createResult.Succeeded) { e.Response.Redirect("/Account/ExternalLoginFailure"); e.HandleResponse(); } } }
3. 确认ApplicationDbContext配置正确
确保你的ApplicationDbContext继承自IdentityDbContext<IdentityUser>,这样Identity才能正确用EF存储用户数据:
public class ApplicationDbContext : IdentityDbContext<IdentityUser> { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } }
同时在ConfigureServices里要正确配置数据库连接:
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
4. 可选:配置持久化登录Cookie
如果需要让登录状态保持更久(比如「记住我」功能),可以显式配置Identity的Cookie:
services.ConfigureApplicationCookie(options => { options.ExpireTimeSpan = TimeSpan.FromDays(7); options.LoginPath = "/Account/Login"; options.SlidingExpiration = true; // 活动时自动延长有效期 });
做完这些步骤后,外部认证成功后会自动创建/关联本地用户,同时生成登录Cookie,后续请求就能正确识别用户身份了。
内容的提问来源于stack exchange,提问作者g01d
相关产品推荐
相关产品推荐

