【问题标题】:Authentication limit extensive header size身份验证限制扩展标头大小
【发布时间】:2018-11-03 10:40:47
【问题描述】:

我有一个连接到 Identity server 4 身份服务器的 Asp .net mvc 应用程序。当我发布应用程序时,我被这个错误迷住了。

从上游读取响应标头时,上游发送了太大的标头

我已经追踪到这个upstream sent too big header while reading response header from upstream

我无法更改配置,系统管理员已声明我们需要使标题更小。

看了之后,我不得不同意这些标题有点广泛。

应用中的 Startup.cs

services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
        })
        .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
            {

                options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.Authority = Configuration["ServiceSettings:IdentityServerEndpoint"];
                options.RequireHttpsMetadata = true;
                options.ClientId = Configuration["ServiceSettings:ClientId"];
                options.ClientSecret = Configuration["ServiceSettings:secret"];
                options.Scope.Add("testapi");
                options.ResponseType = "code id_token";
                options.SaveTokens = true;
                options.GetClaimsFromUserInfoEndpoint = true;
                options.Events = new OpenIdConnectEvents()
                {
                    OnRemoteFailure = ctx =>
                    {
                        _logger.LogCritical($"Remote Faliure: {ctx.Failure}");
                        ctx.HandleResponse();
                        return Task.FromResult(0);
                    }
                };
            });

我一直在寻找,我似乎无法找到限制这个巨大标题大小的方法。

【问题讨论】:

  • 您需要将身份验证信息存储在服务器上,而不是存储在 cookie 中。这是一个示例代码,展示了如何做到这一点:github.com/aspnet/Security/tree/dev/samples/CookieSessionSample(关键部分是.AddCookie(o => o.SessionStore = new MemoryCacheTicketStore())
  • 奇怪我的代码直接来自Identiy server 4教程。
  • 如果我在本地运行它,它工作正常。该用户还可以登录另一个使用隐式授权的应用程序,该应用程序与这个混合的应用程序相对。 (抱怨索赔规模)
  • 我们遇到了同样的问题(使用 .NET Framework 客户端,但我认为原因在 .NET Core 中是相同的) - 微软中间件和随之而来的加密正在创建这个巨大的饼干。索赔的数量并不重要(或至少不重要)。我们最终按照 Evk 的建议进行了操作——将身份验证信息存储在数据库中并发布我们自己的 cookie。我们将 cookie 从大约 3k 缩小到小于 0.5k,问题就消失了。
  • @m3n7alsnak3 这对无状态运行有何影响?

标签: c# header asp.net-core-mvc identityserver4


【解决方案1】:

默认情况下,cookie 包含所有加密的相关信息,因此当调用您的 api 时 - 您需要做的就是解密 cookie 并使用该信息。

但是,通常不希望将所有内容存储在 cookie 本身中,尤其是在存在大量相关信息的情况下。 Cookie 会随您的 api 的每个请求一起发送,如果它很大 - 很多(相同的)信息基本上是来回发送的。另外,如您所见 - 在某些环境中,cookie 的大小可能会成为限制因素。

因此,与其在 cookie 本身中发送所有信息 - 您可以将该信息存储在其他地方,例如在服务器内存中,并将该信息的唯一标识符放置在 cookie 本身中。

您可以像这样为会话配置商店:

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddCookie(o => o.SessionStore = new MemoryCacheTicketStore());

您可以在 github 上的 asp.net examples 上找到示例 MemoryCacheTicketStore 实现:

public class MemoryCacheTicketStore : ITicketStore
{
    private const string KeyPrefix = "AuthSessionStore-";
    private IMemoryCache _cache;

    public MemoryCacheTicketStore()
    {
        _cache = new MemoryCache(new MemoryCacheOptions());
    }

    public async Task<string> StoreAsync(AuthenticationTicket ticket)
    {
        var guid = Guid.NewGuid();
        var key = KeyPrefix + guid.ToString();
        await RenewAsync(key, ticket);
        return key;
    }

    public Task RenewAsync(string key, AuthenticationTicket ticket)
    {
        var options = new MemoryCacheEntryOptions();
        var expiresUtc = ticket.Properties.ExpiresUtc;
        if (expiresUtc.HasValue)
        {
            options.SetAbsoluteExpiration(expiresUtc.Value);
        }
        options.SetSlidingExpiration(TimeSpan.FromHours(1)); // TODO: configurable.

        _cache.Set(key, ticket, options);

        return Task.FromResult(0);
    }

    public Task<AuthenticationTicket> RetrieveAsync(string key)
    {
        AuthenticationTicket ticket;
        _cache.TryGetValue(key, out ticket);
        return Task.FromResult(ticket);
    }

    public Task RemoveAsync(string key)
    {
        _cache.Remove(key);
        return Task.FromResult(0);
    }
}

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2012-05-10
  • 1970-01-01
  • 2019-06-19
  • 2021-09-26
  • 2015-03-07
  • 2015-09-09
  • 2012-06-22
  • 2019-02-06
相关资源
最近更新 更多