.NET8+Umbraco13下按User-Agent配置不同Identity Cookie名称
问题根源
- Umbraco 13会自行配置ASP.NET Core Identity选项,直接使用
ConfigureApplicationCookie可能被Umbraco的配置覆盖,导致自定义事件未触发。 - 直接修改
context.Options.Cookie.Name会修改全局配置,引发并发请求下的Cookie名称冲突问题。
步骤1:修复自定义事件不触发的问题
首先确保自定义CookieAuthenticationEvents被正确注册并关联到Identity的Application认证方案:
- 注册自定义事件类为Scoped服务:
builder.Services.AddScoped<CustomCookieAuthenticationEvents>();
- 使用
PostConfigure将事件关联到IdentityConstants.ApplicationScheme的Cookie配置:
builder.Services.PostConfigure<CookieAuthenticationOptions>(IdentityConstants.ApplicationScheme, options => { options.EventsType = typeof(CustomCookieAuthenticationEvents); });
步骤2:安全动态设置Cookie名称(避免全局冲突)
不要直接修改全局Options.Cookie.Name,而是通过自定义CookieAuthenticationHandler在每个请求的上下文中动态设置Cookie名称,同时确保认证时能正确匹配对应名称的Cookie:
自定义认证Handler
public class DynamicCookieNameAuthenticationHandler : CookieAuthenticationHandler { public DynamicCookieNameAuthenticationHandler(IOptionsMonitor<CookieAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) { } // 认证时根据User-Agent查找对应Cookie protected override Task<AuthenticateResult> HandleAuthenticateAsync() { var userAgent = Context.Request.Headers["User-Agent"].ToString(); Options.Cookie.Name = GetCookieName(userAgent); return base.HandleAuthenticateAsync(); } // 登录时根据User-Agent设置Cookie名称 protected override Task HandleSignInAsync(ClaimsPrincipal user, AuthenticationProperties properties) { var userAgent = Context.Request.Headers["User-Agent"].ToString(); Options.Cookie.Name = GetCookieName(userAgent); return base.HandleSignInAsync(user, properties); } // 根据User-Agent判断Cookie名称的逻辑 private string GetCookieName(string userAgent) { return userAgent.Contains("custom-user-agent") ? "MobileAuthCookie" : "DefaultAuthCookie"; } }
注册自定义Handler到Umbraco的Identity配置
在Umbraco初始化后,替换IdentityConstants.ApplicationScheme的默认Handler:
builder.Services.AddUmbraco(builder.Environment, builder.Configuration) .AddBackOffice() .AddWebsite() .AddDeliveryApi() .AddComposers() .Build(); // 替换默认的Cookie认证Handler为自定义实现 builder.Services.PostConfigure<AuthenticationOptions>(options => { var identityScheme = options.Schemes.FirstOrDefault(s => s.Name == IdentityConstants.ApplicationScheme); if (identityScheme != null) { identityScheme.HandlerType = typeof(DynamicCookieNameAuthenticationHandler); } }); // 注册自定义Handler服务 builder.Services.AddScoped<DynamicCookieNameAuthenticationHandler>();
替代方案:通过ResponseSignIn事件替换Cookie
如果不想自定义Handler,也可以在ResponseSignIn事件中删除默认Cookie,添加自定义名称的Cookie:
public class CustomCookieAuthenticationEvents : CookieAuthenticationEvents { public override Task ResponseSignIn(CookieResponseSignInContext context) { var userAgent = context.HttpContext.Request.Headers["User-Agent"].ToString(); string targetCookieName = userAgent.Contains("custom-user-agent") ? "MobileAuthCookie" : "DefaultAuthCookie"; // 获取刚添加的默认Cookie var defaultCookie = context.Response.Cookies.FirstOrDefault(c => c.Name == context.Options.Cookie.Name); if (defaultCookie != null) { // 删除默认Cookie context.Response.Cookies.Delete(context.Options.Cookie.Name); // 添加自定义名称的Cookie,复制原有的选项 context.Response.Cookies.Append(targetCookieName, defaultCookie.Value, defaultCookie.Options); } return base.ResponseSignIn(context); } // 认证时需要根据User-Agent查找对应Cookie public override Task ValidatePrincipal(CookieValidatePrincipalContext context) { var userAgent = context.HttpContext.Request.Headers["User-Agent"].ToString(); string targetCookieName = userAgent.Contains("custom-user-agent") ? "MobileAuthCookie" : "DefaultAuthCookie"; // 检查当前请求是否有目标Cookie,没有则标记认证失败 if (!context.HttpContext.Request.Cookies.ContainsKey(targetCookieName)) { context.RejectPrincipal(); return context.HttpContext.SignOutAsync(IdentityConstants.ApplicationScheme); } return base.ValidatePrincipal(context); } }
这种方式需要手动处理认证时的Cookie查找,不如自定义Handler简洁,因此优先推荐自定义Handler的方案。
内容的提问来源于stack exchange,提问作者gtu
相关产品推荐
相关产品推荐

