Razor视图中基于策略的授权403错误排查
问题:Razor页面授权403排查
已配置Razor页面授权,但用户已持有对应声明仍返回403未授权,具体配置及代码如下:
1. Razor页面授权配置
[Authorize(Policy = ClaimsPolicies.ViewAdminClaim)] [BindProperties] public class EditCompanyModel(ApplicationDbContext applicationDbContext) : PageModel
2. 策略常量定义
public const string ViewAdminClaim = "View Admin Claim";
3. 授权策略启动配置
_ = services.AddAuthorization(options => { options.AddPolicy(ClaimsPolicies.ViewAdminClaim, policy => policy.RequireClaim(DefaultClaims.ViewAdminClaim, "Yes")); });
4. 登录逻辑(LoginAsync)
public async Task<Response> LoginAsync(CookieRequest request) { ApplicationUser? user = await _userManager.FindByEmailAsync(request.Email); if (user == null) { return Response.Fail("Invalid user"); } if (user.IsActive == false) { return Response.Fail("User account deactivated"); } bool passwordIsCorrect = await _userManager.CheckPasswordAsync(user, request.Password); if (!passwordIsCorrect) { return Response.Fail("Incorrect Password"); } Claim[] customClaims = [ new Claim("tenant", user.TenantId) ]; ClaimsPrincipal claimsPrincipal = await _signInManager.CreateUserPrincipalAsync(user); if (claimsPrincipal.Identity is ClaimsIdentity claimsIdentity) { claimsIdentity.AddClaims(customClaims); } await _signInManager.Context.SignInAsync(IdentityConstants.ApplicationScheme, claimsPrincipal); return Response.Success(); }
5. 登录页模型
[AllowAnonymous] public class LoginModel : PageModel { public CookieRequest cookieRequest { get; set; } public IActionResult OnGet() { return User.Identity.IsAuthenticated ? Redirect("/") : Page(); } }
6. 调试获取的ClaimsPrincipal声明
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: 778a23b9-807e-4289-a2b9-49e5f0921525" "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: admin@admin.com.test" "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress: admin@admin.com" "AspNet.Identity.SecurityStamp: PJHVEWTBNDUGPV5ONJAR776VO5W6JOF7" "http://schemas.microsoft.com/ws/2008/06/identity/claims/role: Sys Admin" "View Admin Claim: Yes" "tenant: test"
7. Program.cs中间件配置
app.UseCors("defaultPolicy"); app.UseHttpsRedirection(); app.UseStatusCodePagesWithRedirects("/NotFound"); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseMiddleware<TenantResolver>(); app.MapRazorPages(); app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); app.MapControllers(); app.UseSession(); app.Run();
排查点:
- ClaimType匹配一致性:检查
DefaultClaims.ViewAdminClaim的字符串值是否和调试中显示的声明Type("View Admin Claim")完全一致,包括大小写、空格等细节,策略的RequireClaim对ClaimType的匹配是区分大小写的。 - 中间件顺序错误:
UseSession()当前放在MapRazorPages()之后,正确顺序应移到UseRouting()之后、UseAuthentication()之前,否则可能影响身份会话数据的读取。调整后顺序:app.UseRouting(); app.UseSession(); app.UseAuthentication(); app.UseAuthorization(); app.UseMiddleware<TenantResolver>(); app.MapRazorPages(); // 其他映射逻辑 - TenantResolver中间件影响:该中间件放在授权之后,可能在授权完成后修改请求上下文导致身份信息异常,可尝试将其移到
UseAuthorization()之前,或检查中间件内部是否有修改ClaimsPrincipal的逻辑。 - 认证Scheme一致性:确认
AddAuthentication()配置中默认Scheme是否为IdentityConstants.ApplicationScheme,需和登录时使用的Scheme保持一致。
内容的提问来源于stack exchange,提问作者Sanjeev-e-jeevs
相关产品推荐
相关产品推荐

