Blazor Server端:为Controller/Razor Page添加身份验证授权
解决Blazor Server中Controller/Razor Page的身份验证问题
1. 修正中间件顺序
Blazor Server的中间件顺序有严格要求,错误顺序会直接导致认证/授权失效:
UseAuthentication()必须在UseAuthorization()之前- 认证、授权中间件必须放在
MapBlazorHub()和MapFallbackToPage()之前 - 最后映射Controller和Razor Page的路由
示例代码(Program.cs):
app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); // 先执行认证,再执行授权 app.UseAuthentication(); app.UseAuthorization(); // Blazor核心路由配置 app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); // 映射Controller和Razor Page路由 app.MapControllers(); app.MapRazorPages();
2. 配置默认认证方案
在服务注册阶段,明确指定默认认证方案为Cookie(与Blazor Server的默认认证体系对齐),同时配置登录跳转路径:
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.LoginPath = "/Login"; // 和Blazor组件中的登录页路由保持一致 options.AccessDeniedPath = "/AccessDenied"; // 可选:配置Cookie过期时间、SameSite属性等参数 }); // 注册授权服务 builder.Services.AddAuthorization();
3. 同步自定义AuthenticationStateProvider与Cookie认证
自定义的AuthenticationStateProvider必须和Cookie认证同步,才能让Controller/Razor Page识别用户身份:
- 先注册
IHttpContextAccessor用于操作Cookie:
builder.Services.AddHttpContextAccessor();
- 在自定义Provider中,基于Cookie的
ClaimsPrincipal生成认证状态,同时在登录/登出时同步更新Cookie和Blazor组件状态:
public class CustomAuthenticationStateProvider : AuthenticationStateProvider { private readonly IHttpContextAccessor _httpContextAccessor; public CustomAuthenticationStateProvider(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } public override async Task<AuthenticationState> GetAuthenticationStateAsync() { // 从HttpContext获取Cookie中的用户身份信息 var principal = _httpContextAccessor.HttpContext?.User ?? new ClaimsPrincipal(); return await Task.FromResult(new AuthenticationState(principal)); } public async Task Login(string username) { var claims = new List<Claim> { new Claim(ClaimTypes.Name, username) }; var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); var principal = new ClaimsPrincipal(identity); // 写入登录Cookie,供Controller/Razor Page识别 await _httpContextAccessor.HttpContext.SignInAsync( CookieAuthenticationDefaults.AuthenticationScheme, principal); // 通知Blazor组件更新认证状态 NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(principal))); } public async Task Logout() { // 清除登录Cookie await _httpContextAccessor.HttpContext.SignOutAsync( CookieAuthenticationDefaults.AuthenticationScheme); // 通知Blazor组件更新状态 NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(new ClaimsPrincipal()))); } }
4. 为Controller/Razor Page添加[Authorize]特性
完成以上配置后,直接在Controller或Razor Page的类/方法上添加[Authorize]特性即可,未认证用户访问时会自动跳转到配置的登录页:
[Authorize] public class DownloadController : Controller { public IActionResult GetFile() { // 仅认证用户可访问此方法 return File("wwwroot/files/sample.pdf", "application/pdf", "sample.pdf"); } }
关键注意事项
- 自定义
AuthenticationStateProvider不能单独维护内存中的用户信息,必须基于Cookie的ClaimsPrincipal生成认证状态,否则Controller无法识别用户身份。 - 中间件顺序绝对不能颠倒,否则会出现「缺少授权中间件」或认证不生效的异常。
- 确保
LoginPath配置的路由和Blazor组件中的登录页一致,避免跳转冲突。
内容的提问来源于stack exchange,提问作者Mike T. Angelo
相关产品推荐
相关产品推荐

