laravel默认强制加密+签名所有cookie,未在encryptcookies的$except中排除的均自动加密;$_cookie直接读取会跳过签名验证且返回乱码,必须用$request->cookie()安全读取。

Laravel 默认对所有写入的 Cookie 执行加密 + 签名(MAC),不是“可选功能”,而是强制安全层。只要没在 EncryptCookies 中显式排除,cookie('name', 'value') 或 response()->cookie() 写入的值,浏览器收到的就是一串形如 eyJpdiI6... 的 base64 字符串,且服务端读取时自动解密验证——你不需要手动调用 Crypt::decrypt()。
Cookie 为什么不能用 $_COOKIE 直接读?
直接读 $_COOKIE['remember_web_59ba36ab7b2f101a4aa88909d3e35c0290512a26'] 拿到的是原始加密字符串(含 iv、value、mac 的 JSON base64),不是明文;更关键的是,它跳过了签名验证逻辑。
- 篡改后仍能读出垃圾数据,但
$request->cookie('name')会返回null(验证失败时静默丢弃) -
$_COOKIE不受HttpOnly限制,若前端 JS 误读,可能造成 XSS 泄露风险 - 绕过
EncryptCookies中间件,等于主动关闭完整性校验
EncryptCookies 中间件怎么决定哪些 Cookie 加密?
它只加密你明确列在 $except 数组里的名称,其余全部加密。默认配置是空数组,意味着“全量加密”。
- 常见需要
except的:第三方 SDK 的调试 Cookie(如_ga)、CDN 缓存标识(如AKA_A2)、纯前端用途且无敏感内容的标记类 Cookie - 不要把
laravel_session或remember_web_*加进$except,它们依赖框架 Session 和认证机制 - 例外列表不支持通配符,必须写全名:
'XSRF-TOKEN'可以,'XSRF-*'无效
加密失败时会发生什么?
当客户端传回的 Cookie 被篡改、APP_KEY 不匹配或 mac 校验失败,$request->cookie('name') 返回 null,不会抛异常,也不会记录错误日志(除非开启 debug 模式并监听 Illuminate\Cookie\CookieDecryptionException)。
- 这不是 bug,是设计:避免攻击者通过报错差异判断 Cookie 是否存在或是否加密
- 如果你依赖该 Cookie 做关键逻辑(如权限跳转),必须做空值判断:
if (!$request->cookie('auth_token')) { abort(401); } - 不要在中间件里对
$request->cookie()结果做json_decode()或unserialize(),Laravel 已帮你处理了序列化/反序列化($serialize = true默认开启)
最常被忽略的一点:加密本身不解决 Cookie 过期问题。即使加密正确,max_age 或 expires 到期后浏览器不再发送,$request->cookie() 依然返回 null——这和加密无关,是 HTTP 协议层行为。











