.NET Core IdentityServerJwt登录成功Cookie设置后无认证User.Identity为空
问题根因与修复方案
1. 认证方案优先级冲突
AddIdentityServerJwt会将系统默认认证方案设置为IdentityServerJwt,该方案优先读取请求头Authorization字段中的JWT令牌,不会主动读取AspNetCore.Identity.ApplicationCookie的内容,导致虽然Cookie存在但认证逻辑未触发,用户信息为空。
修复方式:
如果前后端同域优先使用Cookie认证,修改认证配置指定默认方案为身份Cookie:
services.AddAuthentication(options => { options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme; options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme; }) .AddIdentityServerJwt();
如果需要同时支持Cookie和JWT两种认证方式,可在需要读取用户信息的Controller或Action上通过[Authorize(AuthenticationSchemes = IdentityConstants.ApplicationScheme)]显式指定使用Cookie认证。
2. 接口未添加[Authorize]特性
如果目标接口没有加[Authorize]特性,ASP.NET Core默认不会执行认证流程,HttpContext.User会一直保持未认证状态,所有字段均为空。只需要在对应控制器或Action上添加[Authorize]特性即可触发认证逻辑。
3. 声明映射不匹配
IdentityServer默认生成的用户声明中,用户名字段对应的声明类型为name,而User.Identity.Name默认读取的是http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name类型的声明,会出现读取不到值的情况,添加如下配置即可修复:
services.Configure<IdentityOptions>(options => { options.ClaimsIdentity.UserNameClaimType = "name"; });
4. JWT认证场景下未携带令牌
如果使用JWT认证模式,SignInManager.PasswordSignInAsync只会生成身份Cookie,不会返回JWT令牌给前端,你需要额外调用IdentityServer的token端点获取JWT,前端后续请求在Authorization头中携带Bearer {token}才能完成认证。
额外注意
你当前配置将Cookie的HttpOnly属性设为了false,存在XSS攻击盗取Cookie的安全风险,无特殊需求建议改回默认的true。
内容的提问来源于stack exchange,提问作者mudale

