asp.net core cookie认证只存储加密票据(ticket),不存用户对象;必须将用户信息转为claims,禁用自定义序列化,控制cookie体积并严格配置httponly、secure等安全选项。

ASP.NET Core 的 Cookie 认证不存用户数据到 Cookie 里,它只存一个加密后的票据(ticket),不是你手动序列化 UserInfo 放进去的字符串。想“把对象存进认证 Cookie”,这条路走不通,也极不安全。
CookieAuthenticationOptions 不接受自定义序列化逻辑
框架内部用 TicketDataFormat 将 AuthenticationTicket 加密序列化为字符串,再写入 Cookie。你无法替换这个序列化器去塞 JSON 或二进制对象 —— 即使强行改写,也会破坏签名验证,导致 401。
-
SignInAsync接收的是ClaimsPrincipal,不是任意对象;所有用户信息必须转成Claim才能进票据 - 试图在
ClaimsPrincipal里塞大对象(如byte[]或嵌套 JSON 字符串)会显著增大 Cookie 体积,容易触发浏览器 4KB 限制或 400 Bad Request - 框架不会帮你自动 JSON 序列化
Claim.Value;如果你传入一个对象,.ToString()后存进去,读出来就是类似MyApp.UserInfo这种无意义字符串
想存用户实体?用 Claims + 自定义 ClaimType
正确做法是把必要字段拆成标准或自定义 Claim,而不是打包整个对象:
var claims = new List<claim>
{
new Claim(ClaimTypes.Name, user.UserName),
new Claim("UserId", user.Id.ToString()),
new Claim("UserLevel", user.UserLevel),
new Claim("AvatarUrl", user.AvatarUrl ?? "")
};
var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
var principal = new ClaimsPrincipal(identity);
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
</claim>
- 读取时直接用
User.FindFirst("UserId")?.Value,无需反序列化 - 敏感字段(如密码、token)绝不能放进 Claim;认证票据一旦签发就不可篡改,也不可撤销,只适合放只读、低敏感度标识信息
- ClaimType 建议用 URI 形式(如
"https://myapp.com/claims/userlevel")避免命名冲突,尤其在多租户或联合作场景下
Cookie 太大?别硬塞,改用 Session 或分布式缓存
当用户信息超过 1.5KB(含加密开销),或需要频繁更新(如在线状态、未读消息数),就该放弃“全量存 Cookie”的思路:
- 保留最小化 Claim(仅
Name、UserId、Role),其余查IDistributedCache或数据库,用UserId当 key - 若用 Session,注意
AddSession必须在AddAuthentication之前注册,且 Session 中间件要放在UseAuthentication之后 - 不要用
HttpContext.Session.SetString("user", JsonConvert.SerializeObject(u))存完整对象 —— Session 默认基于内存,重启即丢;生产环境务必配 Redis 或 SQL Server
加密和安全配置漏一项,整个认证就形同虚设
即使 Claims 拆得再规范,如果 CookieAuthenticationOptions 安全项没显式设,Cookie 仍可能被 XSS 窃取或 HTTP 明文传输:
-
CookieHttpOnly = true:禁用document.cookie读取,防 XSS;不设等于裸奔 -
CookieSecurePolicy = CookieSecurePolicy.Always:强制 HTTPS 下发送;开发时若用 HTTP,临时设SameAsRequest,但上线前必须改回Always -
SlidingExpiration = false:若需固定 2 小时过期(不因用户操作重置),必须关滑动;默认true容易造成“用户挂机一星期还登录着”的误判 - 绝对不要启用
UseCookiePolicy()(尤其 .NET Core 3.1 及更早模板自带),它会覆盖你精心配置的Expires和Secure标志
真正难的不是怎么存,而是搞清哪些信息“必须”进 Cookie,哪些“不该”进,以及怎么让那张票据既够用又足够轻、足够安全。











