Postman使用NTLM认证调用带声明授权的ASP.NET Core API返回403问题
问题原因分析与解决方法
你遇到的403错误本质是Postman发起的请求对应的认证身份,没有携带你策略要求的OurReadType、OurWriteType自定义声明,认证本身是成功的所以不会返回401,但授权校验不通过所以返回403,和你去掉策略就可以访问的现象完全吻合。
常见原因
- 自定义声明仅注入给了前端认证链路,没有覆盖Windows原生认证链路
大部分出现该问题的项目,都是给前端做了混合认证:前端首次Windows认证通过后,后端会签发包含自定义读写声明的JWT令牌,后续前端请求带JWT即可拿到声明;但Postman直接走NTLM原生Windows认证,你没有为这类请求单独追加自定义声明,导致身份里只有Windows自带的SID、用户名等基础声明,没有你自定义的权限声明。 - Postman的NTLM配置错误,认证的不是预期的域账号
配置NTLM时如果没有正确填写域名字段,会导致Postman用本地账号而非域账号完成认证,你的权限声明是绑定域账号的,自然无法获取到对应权限。 - 声明转换逻辑依赖前端默认携带的请求参数
如果你的自定义声明生成逻辑(比如IClaimsTransformation实现)依赖前端默认携带的Cookie、自定义请求头等参数,Postman没有配置对应参数的话,就不会触发自定义声明的追加逻辑。
排查步骤
首先添加一个无授权限制的调试接口,输出当前用户的所有声明:
[HttpGet("debug/claims")] public IActionResult GetCurrentUserClaims() { return Ok(User.Claims.Select(c => new { c.Type, c.Value }).ToList()); }
分别用前端、Postman调用该接口,对比返回的声明列表,确认Postman的返回中是否缺少OurReadType、OurWriteType两个自定义声明。
对应解决方法
声明链路覆盖不全的解决方法
实现IClaimsTransformation接口,为所有通过认证的用户统一追加自定义声明,覆盖Windows原生认证场景:
public class CustomClaimTransformer : IClaimsTransformation { // 可注入你的用户权限查询服务 private readonly IUserPermissionService _permissionService; public CustomClaimTransformer(IUserPermissionService permissionService) { _permissionService = permissionService; } public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal) { if (principal.Identity?.IsAuthenticated == true) { var userName = principal.Identity.Name; // 根据用户名查询对应的读写权限 var hasReadPermission = await _permissionService.CheckReadPermission(userName); var hasWritePermission = await _permissionService.CheckWritePermission(userName); var claims = new List<Claim>(); if (hasReadPermission) claims.Add(new Claim("OurReadType", "OurReadValue")); if (hasWritePermission) claims.Add(new Claim("OurWriteType", "OurWriteValue")); if (claims.Any()) { principal.AddIdentity(new ClaimsIdentity(claims)); } } return principal; } }
在Startup.cs中注册该服务:
services.AddScoped<IClaimsTransformation, CustomClaimTransformer>();
NTLM配置错误的解决方法
检查Postman的NTLM配置:
- 域名字段填写你公司的正确域
- 用户名使用
域名\用户名的完整格式填写 - 确保填写的账号确实是你分配了读写权限的域账号
依赖参数缺失的解决方法
对比前端请求的头信息、Cookie信息,把声明转换逻辑依赖的参数在Postman中配置同步即可。
内容的提问来源于stack exchange,提问作者Martijn
相关产品推荐
相关产品推荐

