如何基于ASP.NET Core Identity实现Blazor多端Cookie与Bearer认证?
ASP.NET Core Identity 多认证方案实现答疑
1. 关于认证授权代码的必要性
- 当使用ASP.NET Core Identity模板(如Blazor Web App、带Identity的MVC项目)时,模板已在底层自动注册
AddAuthentication()服务,并在中间件管道中添加UseAuthentication()和UseAuthorization(),无需手动编写。 - 若从空项目搭建,或需自定义认证方案(如同时支持Cookie和Bearer),则必须手动添加:
builder.Services.AddAuthentication():注册认证核心服务,用于管理所有认证方案。app.UseAuthentication():中间件,负责在请求管道中验证用户身份,将认证信息绑定到HttpContext.User。app.UseAuthorization():中间件,基于已验证身份执行授权逻辑,必须放在UseAuthentication()之后,否则授权时无法获取用户身份。
2. 同时支持Cookie和Bearer认证的正确实现
标准Identity配置+双认证方案(推荐)
放弃AddIdentityApiEndpoints的简化方式,用标准流程配置双认证:
- 注册Identity服务(含角色与SignInManager)
builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); // 启用角色支持,注册SignInManager builder.Services.AddIdentity<ApplicationUser, IdentityRole>(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultTokenProviders() .AddSignInManager<SignInManager<ApplicationUser>>();
- 配置双认证方案
builder.Services.AddAuthentication(options => { // 全局默认认证方案,可根据需求调整,也可不在全局设置,而是在授权时指定 options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme; }) // Cookie认证(给托管WASM客户端用) .AddCookie(options => { options.LoginPath = "/Account/Login"; options.Cookie.HttpOnly = true; options.Cookie.SecurePolicy = CookieSecurePolicy.Always; }) // JWT Bearer认证(给MAUI Blazor用) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = builder.Configuration["Jwt:Issuer"], ValidAudience = builder.Configuration["Jwt:Audience"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])) }; // 适配Blazor SignalR的Bearer认证(若MAUI用到SignalR) options.Events = new JwtBearerEvents { OnMessageReceived = context => { var accessToken = context.Request.Query["access_token"]; var path = context.HttpContext.Request.Path; if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/hub")) { context.Token = accessToken; } return Task.CompletedTask; } }; });
- 配置多认证授权策略(可选)
若需部分接口同时支持两种认证,可定义专属策略:
builder.Services.AddAuthorization(options => { options.AddPolicy("CookieOrBearer", policy => { policy.AuthenticationSchemes.Add(CookieAuthenticationDefaults.AuthenticationScheme); policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme); policy.RequireAuthenticatedUser(); }); });
在控制器/API上使用:[Authorize(Policy = "CookieOrBearer")]
关于AddIdentityApiEndpoints的补充说明
- 该方法是Identity 7+推出的简化工具,自动生成登录、注册、刷新令牌等REST API端点,但默认未集成角色支持。若需添加角色,可手动补充:
builder.Services.AddIdentityApiEndpoints<ApplicationUser>() .AddRoles<IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>(); // 手动注册SignInManager builder.Services.AddScoped<SignInManager<ApplicationUser>>();
- 安全性方面,只要正确配置JWT密钥、过期时间、验证参数,与标准JWT认证安全性一致,仅封装了基础认证API以减少重复代码。
3. AddIdentityApiEndpoints的作用及移除后仍能运行的原因
- 作用:自动生成一套REST认证API端点(如
/login、/register),专为无状态客户端(如MAUI Blazor)设计,无需手动编写这些接口。 - 移除后仍能运行的原因:若你的托管WASM客户端使用传统Cookie认证,依赖的是Identity自带的登录页面而非自动生成的API,移除后不影响现有功能;但如果MAUI Blazor需要调用这些API获取Bearer令牌,移除后会出现404错误。
内容的提问来源于stack exchange,提问作者Marek Havrila
相关产品推荐
相关产品推荐

