storageless密钥配置指南:对称HMAC与非对称EdDSA签名方案如何选择?
【免费下载链接】storageless:mailbox_with_mail: storage-less PSR-7 session support项目地址: https://gitcode.com/gh_mirrors/st/storageless
storageless(psr7-sessions/storageless)是一个基于 PSR-7 的"无存储"会话库:它不写服务器文件、不用 Redis、不碰$_SESSION,而是把会话数据打包成带签名的 JWT 直接放进 Cookie,由浏览器替你"存"。正因为如此,storageless密钥配置就成了上线前最重要的一步——密钥决定了会话是否会被伪造。本文用通俗的语言讲清楚对称 HMAC 与非对称 EdDSA 两种签名方案的区别、配置步骤和选型建议,帮你一次选对。
为什么 storageless 需要配置密钥?先搞懂签名原理
传统 PHP 会话把数据存在服务器端,客户端只拿一个随机 ID;而 storageless 反其道而行,会话数据本身就在 Cookie 里。既然数据在用户手里,就必须防止用户篡改。
它的做法是:服务端用密钥对 JWT 签名,浏览器每次请求带回 Cookie,服务端验签通过才信任里面的数据。这个过程完全依赖lcobucci/jwt中配置签名算法 + 密钥即可。
默认情况下,Cookie 名为__Secure-slsession,自带Secure、HttpOnly、SameSite=Lax、path=/四项安全属性,你基本不用动它。
方案一:对称 HMAC 签名——最快的 storageless密钥配置方法
什么是对称签名?
HMAC 使用同一个密钥完成签名和验证,类似"一把钥匙开一把锁":你用钥匙锁上箱子,对方用同一把钥匙开箱验证。
适用场景
- 单台服务器或可信内网部署
- 想以最小成本快速接入
- 所有节点都能安全保管密钥
最快配置方法(只需 5 行)
use Lcobucci\JWT\Configuration as JwtConfig; use Lcobucci\JWT\Signer; use Lcobucci\JWT\Signer\Key\InMemory; use PSR7Sessions\Storageless\Http\SessionMiddleware; use PSR7Sessions\Storageless\Http\Configuration as StoragelessConfig; $sessionMiddleware = new SessionMiddleware( new StoragelessConfig( JwtConfig::forSymmetricSigner( new Signer\Hmac\Sha256(), InMemory::base64Encoded('你的随机密钥,至少32字节'), ) ) );其中InMemory::base64Encoded()传入的就是你的签名密钥。完整用法可参考官方文档 docs/configuration.md 和可运行的 examples/index.php 示例。
优缺点速览
- ✅ 配置最简单,只有一份密钥
- ✅ 验签性能好
- ❌ 密钥必须所有节点共享,一旦泄露,攻击者能随意伪造会话
方案二:非对称 EdDSA 签名——多服务器安全配置首选
什么是不对称签名?
非对称签名使用一对密钥:私钥负责签名(写入会话),公钥负责验证(读取会话)。公钥可以随便分发,甚至公开都没关系。
适用场景
- 多台服务器横向扩展
- 想要"读写分离":只有持有私钥的节点能签发会话
- 对外提供会话校验服务,只需下发公钥
配置步骤
先准备密钥对(EdDSA 需要 PHP 的ext-sodium扩展,项目依赖中已声明):
openssl genpkey -algorithm ED25519 -out private_key.pem openssl pkey -in private_key.pem -pubout -out public_key.pem项目测试用的密钥对就放在 test/keys/ 目录(含private_key.pem和public_key.pem),仅供测试,生产环境务必自己生成。
然后配置:
use Lcobucci\JWT\Configuration as JwtConfig; use Lcobucci\JWT\Signer; use Lcobucci\JWT\Signer\Key\InMemory; use PSR7Sessions\Storageless\Http\SessionMiddleware; use PSR7Sessions\Storageless\Http\Configuration as StoragelessConfig; $sessionMiddleware = new SessionMiddleware( new StoragelessConfig( JwtConfig::forAsymmetricSigner( new Signer\Eddsa(), InMemory::file('private_key.pem'), // 私钥:用于签发会话 InMemory::file('public_key.pem'), // 公钥:用于验证会话 ) ) );优缺点速览
- ✅ 私钥只在少数节点保存,公钥可自由分发
- ✅ 支持"只读节点":只拿公钥的服务器无法伪造会话
- ❌ 配置稍复杂,需要管理密钥对和分发流程
对称 HMAC 与非对称 EdDSA:快速对比与选型建议
| 对比维度 | 对称 HMAC (Sha256) | 非对称 EdDSA |
|---|---|---|
| 密钥数量 | 1 个,签名验证共用 | 2 个,私钥签名 / 公钥验证 |
| 密钥分发难度 | 所有节点共享一份 | 只需分发公钥 |
| 配置复杂度 | ⭐ 低 | ⭐⭐ 中 |
| 推荐场景 | 单机、可信内网 | 多服务器、读写分离 |
| 泄露后果 | 密钥泄露 = 会话全可伪造 | 仅私钥泄露才危险 |
| 性能 | 较快 | 略慢,现代 CPU 无感知 |
选型口诀:单机图省事用 HMAC,多机重安全用 EdDSA;只要你的服务将来要扩容,直接上 EdDSA 最省心——毕竟换算法要重新配置并作废所有旧会话。
密钥生成与安全注意事项
无论选哪种方案,都请遵守这几条:
- 用 CSPRNG 生成高熵密钥,不要手打字符串。对称密钥可这样生成:
php -r "echo base64_encode(random_bytes(32));"- 生产密钥绝不入库到 Git,更不要用 test/keys/ 里的测试密钥。
- 定期轮换密钥。注意:更换密钥会立即让所有旧会话验签失败,相当于全体下线,请安排在低峰期。
- 关于签名验证的关键逻辑,可查看 src/Storageless/Http/SessionMiddleware.php 中对
SignedWith约束的使用。
常见问题速答
Q:本地开发没有 HTTPS,Cookie 发不出去怎么办?A:默认__Secure-slsession只在 HTTPS 下工作。本地可用withCookie()方法把 Cookie 改成普通名称并关闭Secure标志,具体示例见官方文档 docs/configuration.md 的"Local development"一节,但生产环境务必保持默认安全配置。
Q:会话能存多少数据?A:Cookie 有 4KB 上限,加上 JWT 的 base64 编码和签名开销,建议会话数据(JSON 编码后)控制在512 字节以内。更多边界说明见 docs/limitations.md。
Q:能不能单独踢掉某个用户的会话?A:storageless 天然不支持单会话作废,唯一的"一键失效"方式是更换全局密钥。这也提醒我们:它适合存放用户 ID、CSRF Token 等非敏感信息,不要放密码、手机号等私密数据。
总结
storageless密钥配置其实只有两个选择:对称 HMAC 求简单,非对称 EdDSA 求安全。中小项目、单机部署直接 HMAC 一把梭;涉及多服务器、需要权限隔离的场景,果断上 EdDSA。无论选哪个,只要记住"密钥要随机、要保密、要轮换",你的无存储会话就能安全稳定地跑起来。
【免费下载链接】storageless:mailbox_with_mail: storage-less PSR-7 session support项目地址: https://gitcode.com/gh_mirrors/st/storageless
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考