You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决IIS Express本地环境下的“Request Too Long”错误?

解决ASP.NET MVC 5中OpenID Connect认证后Cookie过大导致的HTTP 400错误

你遇到的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 18:12:35