.Net Core 2.0自定义授权返回401:认证成功但控制器未执行
问题根源:ClaimsIdentity未指定认证类型
我一眼就看出问题所在了——你在自定义认证Handler的HandleAuthenticateAsync方法里创建ClaimsIdentity时,没有传入认证类型参数!这会导致即使你返回了AuthenticateResult.Success,当前用户的身份依然会被判定为未认证,最终被[Authorize]特性拦截返回401。
为什么会这样?
ClaimsIdentity的IsAuthenticated属性有个关键规则:只有当你在构造它时传入了非空的认证类型(authenticationType),这个属性才会返回true。如果没传这个参数,哪怕你给Identity添加了Claim,它依然会被判定为未认证状态。而[Authorize]特性正是依赖这个属性来判断用户是否合法的,所以它会直接拒绝请求,根本不会走到控制器代码里。
修复方案
修改HandleAuthenticateAsync里创建ClaimsIdentity的代码,把Scheme.Name作为第二个参数传入:
protected override async Task<AuthenticateResult> HandleAuthenticateAsync() { string token = Request.Headers["Authorization"]; if (string.IsNullOrEmpty(token)) return AuthenticateResult.Fail("Failing string"); // Using external service to validate token and get user id int Id = GetUserId(token); return AuthenticateResult.Success( new AuthenticationTicket( new ClaimsPrincipal( // 这里添加Scheme.Name作为认证类型参数 new ClaimsIdentity( new List<Claim>() { new Claim(ClaimTypes.Sid, Id.ToString()) }, Scheme.Name)), Scheme.Name)); }
额外验证点
你可以在调试时检查ClaimsPrincipal.Identity.IsAuthenticated的值:修复前它会是false,修复后就会变成true,此时[Authorize]特性就会允许请求进入控制器执行逻辑了。
内容的提问来源于stack exchange,提问作者Matheus Lacerda
相关产品推荐
相关产品推荐

