php零信任要求每个请求实时校验jwt签名、exp/nbf时效、scope权限及认证上下文,禁用none算法,不依赖$_session或$_cookie,须api网关与业务层双校验并动态比对权限。

PHP 零信任不是加个 JWT 中间件就完事——每个请求必须实时校验签名、时效、scope 和上下文,且不能依赖 $_SESSION 或 $_COOKIE 做任何权限判断。
JWT 解析必须显式指定 algorithms 并禁用 none
常见错误是调用 JWT::decode($token, $key) 却没传 algorithms 参数,导致攻击者可构造 alg:none 的伪造 token 绕过签名验证。
- 必须强制指定
algorithms=["RS256"](或你实际使用的非对称算法),绝不能留空或设为["none"] - 使用
firebase/php-jwt时,JWT::decode()第三个参数必须是非空数组,例如:['RS256'] - 若用对称密钥(HS256),确保
$key是服务端强随机生成、未硬编码在代码里的密钥,且长度 ≥ 256 bit - 解析失败时,必须统一返回
401 Unauthorized,不暴露具体失败原因(如“invalid signature”或“exp expired”)
每次请求都校验 exp/nbf,且只信 time()
JWT 的 exp(过期)和 nbf(生效前)必须在校验阶段由服务端用 time() 实时比对,不能读取 payload 里的 iat 或客户端传的时间戳。
- 检查逻辑应类似:
if (time() >= $payload->exp || time() nbf) { throw new InvalidTokenException(); } - 建议设置合理的时钟偏移容差(如 ±30 秒),但仅用于网络传输延迟补偿,不可用于延长 token 生命周期
- 不要把
exp存进数据库或缓存做二次比对——它只在本次 JWT 解析时起作用 - 若业务要求 token 短期有效(如 5 分钟),需配合前端刷新机制,后端拒绝所有超时 token,不回退兼容
scope/permissions 字段必须动态比对当前接口所需权限
一个 token 拥有 read:users 不代表它能访问 /api/orders——权限校验必须紧贴路由或数据操作入口,而非中间件一次放行。
- 在控制器方法或 Repository 查询前,提取
$payload->scope(数组)或$payload->permissions,并显式比对,例如:in_array('read:orders', $scopes) - 避免用模糊匹配(如
str_starts_with($scope, 'read:')),防止read:orders_dump_all被误认为合法 - 敏感操作(如
DELETE /api/users/{id})应额外检查acr字段是否 ≥ 2,表示已通过 MFA 认证 - 数据库查询前必须做 ABAC/RBAC 校验:例如
User::find($id)前,确认当前 token 的sub与$id匹配,或所属租户一致
绝不信任 $_SESSION 和 $_COOKIE 中的权限字段
零信任下,$_SESSION['role'] 或 $_COOKIE['user_id'] 是典型攻击面——它们由客户端控制或易被会话固定劫持,不能用于任何鉴权决策。
- 若必须用 session,仅限存储已通过 JWT/mTLS 验证后的临时上下文,例如:
$_SESSION['verified_device_id'],且生命周期 ≤ 300 秒(ini_set('session.gc_maxlifetime', 300)) - 禁止从
$_COOKIE读取任何身份或权限信息;所有认证凭据必须来自 Authorization Header 的 Bearer token - API 网关层与业务层必须双校验:网关做基础 token 有效性检查,业务层做 scope + 数据级权限检查,防止绕过中间件直调控制器
- 文件下载、导出等高风险接口,除校验 token 外,路径必须白名单过滤(如
in_array($filename, ['report_q1.pdf', 'summary.csv'])),禁用../路径遍历
真正难的不是写对那几行 JWT::decode(),而是让每个接口、每个查询、每个文件响应都主动参与验证循环——漏掉一个点,整个零信任链就断了。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











