Cookie认证净的核心

本文关键字:核心 认证 Cookie | 更新日期: 2023-09-27 18:18:05

我可以在ITicketStore中使用MemoryCache来存储AuthenticationTicket吗?

背景:我的web应用程序正在使用Cookie认证:

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AutomaticAuthenticate = true,
    AutomaticChallenge = true,
    LoginPath = new PathString("/Authentication/SignIn"),
    LogoutPath = new PathString("/Authentication/SignOut"),
    ReturnUrlParameter = "/Authentication/SignIn"
});

我的web api使用访问令牌(OAuth2)处理授权过程。

有时(在某些浏览器上)会抛出以下异常:

发生未处理的异常:分块cookie不完整。只找到了预期的2个块中的1个,总共4021个字符。可能已超过客户端大小限制。

饼干显然太大了。这很奇怪,因为我没有使用很多声明。它们都是默认声明(nameidentifier, nonce, exp等)。我现在正试图在CookieAuthenticationOptions上实现我自己的ITicketStore作为SessionStoreAuthenticationTicket将存储在MemoryCache中(如本示例中)。我对整个主题非常陌生,不确定,如果这是一个好方法,如果MemoryCache是一个有效的解决方案。

Cookie认证净的核心

可以在ITicketStore中使用MemoryCache来存储AuthenticationTicket吗?

当然,这是我使用了将近一年的实现。

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationScheme = "App.Cookie",
    AutomaticAuthenticate = true,
    AutomaticChallenge = true,
    LoginPath = new PathString("/Authentication/SignIn"),
    LogoutPath = new PathString("/Authentication/SignOut"),
    ReturnUrlParameter = "/Authentication/SignIn",
    SessionStore = new MemoryCacheStore(cache)
});

MemoryCacheStore的实现看起来像这样,它遵循您分享的示例:

public class MemoryCacheStore : ITicketStore
{
    private const string KeyPrefix = "AuthSessionStore-;
    private readonly IMemoryCache _cache;
    public MemoryCacheStore(IMemoryCache cache)
    {
        _cache = cache;
    }
    public async Task<string> StoreAsync(AuthenticationTicket ticket)
    {
        var key = KeyPrefix + Guid.NewGuid();
        await RenewAsync(key, ticket);
        return key;
    }
    public Task RenewAsync(string key, AuthenticationTicket ticket)
    {
        // https://github.com/aspnet/Caching/issues/221
        // Set to "NeverRemove" to prevent undesired evictions from gen2 GC
        var options = new MemoryCacheEntryOptions
        {
            Priority = CacheItemPriority.NeverRemove
        };
        var expiresUtc = ticket.Properties.ExpiresUtc;
        if (expiresUtc.HasValue)
        {
            options.SetAbsoluteExpiration(expiresUtc.Value);
        }    
        options.SetSlidingExpiration(TimeSpan.FromMinutes(60));
        _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);
    }
}