登录态、跨域与缓存的暗战:Cookie / 同源策略 / 缓存实战
2026/7/27 21:18:24
Startup.cs的ConfigureServices方法中,我们可以注册各种认证方案。最简单的例子是使用 Cookie 认证。### 基础 Cookie 认证注册csharp// 在 Startup.cs 的 ConfigureServices 方法中public void ConfigureServices(IServiceCollection services){ // 添加认证服务,并注册默认的 Cookie 方案 services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { // 设置登录路径,当用户未认证时重定向到此路径 options.LoginPath = "/Account/Login"; // 设置 Cookie 名称 options.Cookie.Name = "MyAppCookie"; // 设置 Cookie 过期时间 options.ExpireTimeSpan = TimeSpan.FromHours(1); }); services.AddControllersWithViews();}这段代码做了以下事情:1.AddAuthentication()注册认证服务,并指定默认方案为 Cookie2.AddCookie()注册 Cookie 方案,并配置选项3. 配置登录路径和 Cookie 行为## 三、请求认证:中间件的作用注册方案后,我们需要在请求管道中使用认证中间件。在Configure方法中,我们添加认证中间件来处理每个请求。### 请求认证配置csharp// 在 Startup.cs 的 Configure 方法中public void Configure(IApplicationBuilder app, IWebHostEnvironment env){ if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); } app.UseStaticFiles(); // 添加认证中间件 - 顺序很重要,必须在 UseAuthorization 之前 app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); });}关键点:-UseAuthentication()必须放在UseAuthorization()之前- 中间件的顺序决定了请求处理的流程## 四、深入探究:自定义认证方案当标准方案不满足需求时,我们可以创建自定义认证方案。下面是一个完整的示例,展示如何创建基于 API Key 的认证方案。### 自定义认证处理器实现csharp// 自定义认证方案类public class ApiKeyAuthenticationHandler : AuthenticationHandler<ApiKeyAuthenticationOptions>{ private readonly IConfiguration _configuration; public ApiKeyAuthenticationHandler( IOptionsMonitor<ApiKeyAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IConfiguration configuration) : base(options, logger, encoder, clock) { _configuration = configuration; } protected override async Task<AuthenticateResult> HandleAuthenticateAsync() { // 从请求头中获取 API Key if (!Request.Headers.TryGetValue("X-API-Key", out var apiKeyHeaderValues)) { // 如果没有 API Key,返回认证失败 return AuthenticateResult.Fail("Missing API Key"); } var providedApiKey = apiKeyHeaderValues.FirstOrDefault(); if (string.IsNullOrEmpty(providedApiKey)) { return AuthenticateResult.Fail("Invalid API Key"); } // 验证 API Key 是否有效(这里简单地与配置文件中的值比较) var validApiKey = _configuration["ApiKey"]; if (!string.Equals(providedApiKey, validApiKey, StringComparison.Ordinal)) { return AuthenticateResult.Fail("Invalid API Key"); } // 创建 Claims 和身份标识 var claims = new[] { new Claim(ClaimTypes.Name, "API User"), new Claim(ClaimTypes.Role, "ApiClient"), new Claim("ApiKey", providedApiKey) }; var identity = new ClaimsIdentity(claims, Scheme.Name); var principal = new ClaimsPrincipal(identity); var ticket = new AuthenticationTicket(principal, Scheme.Name); // 返回认证成功结果 return AuthenticateResult.Success(ticket); }}### 自定义认证选项类csharp// 自定义认证选项public class ApiKeyAuthenticationOptions : AuthenticationSchemeOptions{ public const string DefaultScheme = "ApiKey"; public string Scheme => DefaultScheme;}### 在 Startup 中注册自定义方案csharp// 在 ConfigureServices 方法中public void ConfigureServices(IServiceCollection services){ // 注册自定义 API Key 认证方案 services.AddAuthentication(ApiKeyAuthenticationOptions.DefaultScheme) .AddScheme<ApiKeyAuthenticationOptions, ApiKeyAuthenticationHandler>( ApiKeyAuthenticationOptions.DefaultScheme, options => { }); services.AddControllers();}## 五、高级应用:多方案认证与策略在实际项目中,我们可能需要支持多种认证方式。.NET Core 支持多方案认证,并允许通过策略进行细粒度控制。### 多方案认证配置csharppublic void ConfigureServices(IServiceCollection services){ services.AddAuthentication() .AddCookie("CookieAuth", options => { options.LoginPath = "/Account/Login"; options.Cookie.Name = "MyAppCookie"; }) .AddJwtBearer("Bearer", options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidIssuer = "https://myapp.com", ValidateAudience = true, ValidAudience = "https://myapp.com", ValidateLifetime = true, IssuerSigningKey = new SymmetricSecurityKey( Encoding.UTF8.GetBytes("my-secret-key-here")) }; }); // 定义认证策略 services.AddAuthorization(options => { // 策略1:只能通过 Cookie 认证 options.AddPolicy("CookieOnly", policy => { policy.AuthenticationSchemes.Add("CookieAuth"); policy.RequireAuthenticatedUser(); }); // 策略2:Cookie 或 JWT 都可以 options.AddPolicy("Mixed", policy => { policy.AuthenticationSchemes.Add("CookieAuth"); policy.AuthenticationSchemes.Add("Bearer"); policy.RequireAuthenticatedUser(); }); }); services.AddControllers();}### 在控制器中使用策略csharp[ApiController][Route("api/[controller]")]public class SecureController : ControllerBase{ // 使用默认认证方案 [HttpGet("public-data")] [Authorize] public IActionResult GetPublicData() { return Ok("This is public data"); } // 使用 Cookie 认证策略 [HttpGet("cookie-data")] [Authorize(Policy = "CookieOnly")] public IActionResult GetCookieData() { return Ok("This requires Cookie authentication"); } // 使用混合认证策略 [HttpGet("mixed-data")] [Authorize(Policy = "Mixed")] public IActionResult GetMixedData() { return Ok("This accepts both Cookie and JWT"); }}## 六、性能优化与最佳实践### 认证缓存优化对于频繁的 API 请求,我们可以缓存认证结果以提高性能:csharppublic class CachedAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>{ private readonly IMemoryCache _cache; public CachedAuthenticationHandler( IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IMemoryCache cache) : base(options, logger, encoder, clock) { _cache = cache; } protected override async Task<AuthenticateResult> HandleAuthenticateAsync() { var token = Request.Headers["Authorization"].FirstOrDefault(); if (string.IsNullOrEmpty(token)) return AuthenticateResult.Fail("No token"); // 尝试从缓存获取认证结果 var cacheKey = $"auth_{token}"; if (_cache.TryGetValue(cacheKey, out AuthenticateResult cachedResult)) { return cachedResult; } // 执行实际的认证逻辑 var result = await PerformAuthenticationAsync(token); // 缓存认证结果,设置过期时间 if (result.Succeeded) { _cache.Set(cacheKey, result, TimeSpan.FromMinutes(5)); } return result; } private Task<AuthenticateResult> PerformAuthenticationAsync(string token) { // 实际的认证逻辑 return Task.FromResult(AuthenticateResult.Fail("Not implemented")); }}## 总结通过本文的探究,我们深入理解了 .NET Core 认证模块的核心机制。从基础的 Cookie 认证注册,到请求认证中间件的配置,再到自定义认证方案的实现,每一步都揭示了认证模块的灵活性和可扩展性。关键要点:1.注册方案是认证的起点,通过AddAuthentication和AddCookie/AddJwtBearer等方法配置2.请求认证通过UseAuthentication中间件实现,顺序至关重要3.自定义方案允许我们根据业务需求创建独特的认证逻辑4.多方案与策略提供了细粒度的访问控制能力5.性能优化如缓存认证结果,可以提升系统响应速度在实际开发中,应根据应用场景选择合适的认证方案,并注意安全性和性能的平衡。掌握这些知识,将帮助你在 .NET Core 应用中构建安全、高效的认证系统。