Asp.net MVC对接IdentityServer4时请求头过大问题求助
针对你遇到的Nginx报错upstream sent too big header while reading response header from upstream,且无法修改服务器配置的情况,咱们可以从Asp.net应用本身入手,通过缩小请求头承载的内容来解决问题。结合你的Startup配置,给你几个具体的实现方案:
1. 过滤不必要的Claims,减小Cookie体积
默认情况下,GetClaimsFromUserInfoEndpoint = true会把IdentityServer返回的所有用户Claims都添加到认证Cookie中,这会让Cookie变得非常大。你可以通过配置ClaimActions来只保留业务需要的Claims,删除多余的:
修改你的OpenIdConnect配置,添加ClaimActions规则:
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options => { // 其他原有配置... options.GetClaimsFromUserInfoEndpoint = true; // 示例:删除不需要的Claims(替换成你实际不需要的Claim类型) options.ClaimActions.DeleteClaim("address"); options.ClaimActions.DeleteClaim("birthdate"); // 或者更彻底:只保留指定的Claims,其余全部删除 options.ClaimActions.MapUniqueJsonKey("name", "name"); options.ClaimActions.MapUniqueJsonKey("email", "email"); options.ClaimActions.MapUniqueJsonKey("sub", "sub"); options.ClaimActions.DeleteAllClaimsExcept("name", "email", "sub"); // 原有Events配置... });
这样Cookie里只会保留你真正需要的用户信息,体积会大幅缩小,对应的请求头也会变小。
2. 将Tokens存储到Session,而非Cookie中
你的配置里设置了SaveTokens = true,这会把access_token、id_token等直接存在Cookie里——这些Token本身可能很长(尤其是包含大量Claims的JWT),是请求头过大的重要原因。我们可以改成把Tokens存储到Session中,Cookie里只存SessionID:
第一步:启用Session支持
在ConfigureServices中添加Session配置:
services.AddSession(options => { options.IdleTimeout = TimeSpan.FromHours(1); // 根据你的业务设置超时时间 options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; });
在Configure方法中,确保UseSession在UseAuthentication之前执行:
app.UseSession(); app.UseAuthentication(); app.UseAuthorization(); // 其他中间件...
第二步:修改OpenIdConnect配置,把Tokens存到Session
去掉SaveTokens = true,然后在OnTokenValidated事件中保存Tokens到Session:
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options => { // 其他原有配置... // 注释掉SaveTokens // options.SaveTokens = true; options.Events = new OpenIdConnectEvents() { OnRemoteFailure = ctx => { _logger.LogCritical($"Remote Faliure: {ctx.Failure}"); ctx.HandleResponse(); return Task.FromResult(0); }, OnTokenValidated = ctx => { // 将Token存储到Session ctx.HttpContext.Session.SetString("access_token", ctx.TokenEndpointResponse.AccessToken); ctx.HttpContext.Session.SetString("id_token", ctx.TokenEndpointResponse.IdToken); if (!string.IsNullOrEmpty(ctx.TokenEndpointResponse.RefreshToken)) { ctx.HttpContext.Session.SetString("refresh_token", ctx.TokenEndpointResponse.RefreshToken); } return Task.CompletedTask; } }; });
之后你需要使用Token时,直接从Session中读取即可,这样Cookie的体积会变得非常小。
3. 启用Cookie压缩
Asp.net Core 2.1及以上版本支持Cookie压缩,开启后可以自动压缩Cookie内容,进一步减小请求头大小:
修改AddCookie的配置:
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => { options.Cookie.Name = "YourAppAuthCookie"; options.Cookie.HttpOnly = true; // 启用Cookie压缩 options.CompressCookie = true; })
这个方案可以和前两个方案结合使用,进一步优化请求头大小。
内容的提问来源于stack exchange,提问作者Linda Lawton - DaImTo

