Cookie 身份验证 ASP.NET Core

Posted

技术标签:

【中文标题】Cookie 身份验证 ASP.NET Core【英文标题】:Cookie Authentication ASP.NET Core 【发布时间】:2017-03-30 12:57:27 【问题描述】:

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

背景:我的网络应用正在使用 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 个字符。可能已超出客户端大小限制。

cookie 显然太大了。这很奇怪,因为我不使用很多声明。所有这些都是默认声明(nameidentifier、nonce、exp 等)。我现在正在尝试在CookieAuthenticationOptions 上实现我自己的ITicketStore 作为SessionStoreAuthenticationTicket 将存储在 MemoryCache 中(就像在这个 sample 中一样)。我对整个主题很陌生,不确定这是否是一种好方法以及MemoryCache 是否是有效的解决方案。

【问题讨论】:

github.com/aspnet/Security/issues/830 这个 github issue 可能对你有帮助。 【参考方案1】:

我可以在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 的实现如下所示,它遵循您共享的 the example:

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);
    

【讨论】:

感谢您的回复。与使用 cookie 相比,这种方法有什么缺点吗? Web 应用程序内存不足是我唯一能想到的。 它实际上是在使用 cookie,因此是 UseCookieAuthentication。如果内存是一个问题,请考虑这些过期并且一旦过期就会丢失内存的事实,因为它们将被释放和清理。此外,它们很小……同样,取决于您设置托管应用程序的方式,可以确定它是否会产生影响。您希望能够扩展。 没有内存并不是真正的问题。我只是在考虑一般的缺点。是的,它使用 cookie,但 AuthenticationTicket 本身并没有存储在 cookie 中,只有参考。这是正确的吗? 不正确,cookie 中的所有内容都被反序列化为 ClaimsPrinicipal .. 而这个原则构成了 AuthenticationTicket github.com/aspnet/Security/blob/…。 啊,好吧,这很有道理。但是必须为用户在本地存储一些东西吗?也许是从StoreAsync 方法返回的密钥?或者服务器是如何识别用户的?

以上是关于Cookie 身份验证 ASP.NET Core的主要内容,如果未能解决你的问题,请参考以下文章

ASP.Net Core Cookie 身份验证

ASP.NET Core 身份验证 cookie 只收到一次

如何手动解密 ASP.NET Core 身份验证 cookie?

ASP.NET Core 使用Cookie验证身份

如何使 ASP.NET Core 中的身份验证 cookie 无效?

如何使用 Postman 使用 cookie 身份验证测试 ASP.NET Core Web API?