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
作为SessionStore
。 AuthenticationTicket
将存储在 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?