如何解决IIS Express本地环境下的“Request Too Long”错误?
你遇到的HTTP 400(Bad Request - Request Too Long)错误,核心原因是OpenID认证后生成的Cookie包含大量Claims,体积超出了浏览器或服务器对Cookie/请求头的大小限制。你之前配置的maxQueryStringLength、maxRequestLength等参数都是针对请求体或URL的设置,和Cookie长度限制无关,所以无法解决问题。
以下是针对性的解决方案:
1. 筛选不必要的Claims(优先推荐)
最根本的解决方式是只保留业务必需的Claims,减少Cookie内容体积。在OpenIdConnect的认证配置中,通过OnTokenValidated事件过滤Claims:
// 在Startup.Auth.cs的OpenIdConnect配置中添加 app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions { // 其他原有配置(ClientId、Authority等) Notifications = new OpenIdConnectAuthenticationNotifications { OnTokenValidated = n => { // 仅保留业务需要的Claims,比如用户ID、用户名等 var essentialClaims = n.AuthenticationTicket.Identity.Claims .Where(c => c.Type == ClaimTypes.NameIdentifier || c.Type == ClaimTypes.Name || c.Type == "your-custom-claim-type" // 替换为你需要的Claim类型 ) .ToList(); // 生成新的身份标识,替换原有包含大量Claims的标识 var newIdentity = new ClaimsIdentity( essentialClaims, n.AuthenticationTicket.Identity.AuthenticationType ); n.AuthenticationTicket = new AuthenticationTicket(newIdentity, n.AuthenticationTicket.Properties); return Task.CompletedTask; } } });
2. 配置Cookie拆分与请求头限制
如果无法大幅减少Claims数量,可以通过Owin的ChunkingCookieManager将大Cookie拆分为多个符合浏览器限制的小Cookie,同时调整IIS的请求头大小限制:
步骤1:启用Cookie拆分
在Cookie认证配置中指定CookieManager为ChunkingCookieManager:
app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathString("/Account/Login"), // 使用ChunkingCookieManager自动拆分大Cookie CookieManager = new ChunkingCookieManager() });
步骤2:调整IIS请求头大小限制
在Web.config的requestFiltering中添加maxHeaderSize,允许更大的请求头(因为Cookie包含在请求头中):
<system.webServer> <security> <requestFiltering> <requestLimits maxAllowedContentLength="100000000" maxQueryString="20000" maxUrl="20000" maxHeaderSize="65536" /> <!-- 可根据实际情况调整,单位为字节 --> </requestFiltering> </security> </system.webServer>
3. 使用Session存储Claims(备选方案)
如果Claims数量确实过多,可将Claims存储在Session中,仅在Cookie中存储Session ID,彻底减少Cookie体积:
配置Session存储
// 自定义Session存储示例(单服务器可用内存存储,多服务器建议用Redis/数据库) public class MemoryCacheSessionStore : IAuthenticationSessionStore { private readonly MemoryCache _cache = MemoryCache.Default; private readonly string _prefix = "AuthSession_"; public Task<string> StoreAsync(AuthenticationTicket ticket) { var key = _prefix + Guid.NewGuid().ToString(); _cache.Set(key, ticket, DateTimeOffset.UtcNow.AddHours(1)); // 设置过期时间 return Task.FromResult(key); } public Task RenewAsync(string key, AuthenticationTicket ticket) { _cache.Set(key, ticket, DateTimeOffset.UtcNow.AddHours(1)); return Task.CompletedTask; } public Task<AuthenticationTicket> RetrieveAsync(string key) { return Task.FromResult(_cache.Get(key) as AuthenticationTicket); } public Task RemoveAsync(string key) { _cache.Remove(key); return Task.CompletedTask; } } // 在Startup.Auth.cs中配置Cookie认证使用Session存储 app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathString("/Account/Login"), SessionStore = new MemoryCacheSessionStore() });
注意:内存存储仅适合单服务器部署场景,多服务器集群需使用分布式存储(如Redis)来保证Session共享。
内容的提问来源于stack exchange,提问作者Jay
相关产品推荐
相关产品推荐

