webman权限管理系统必须将rbac模型与token解析、上下文绑定、权限校验强耦合,否则role字段可被伪造越权;需手动调用jwt::decode()校验全部标准字段,捕获四类异常返回401,并将权限存入$request->attr('permissions')供后续中间件统一校验。

Webman 权限管理系统不能靠“装个 JWT 插件 + 写几个 role 字段”就上线,RBAC 模型必须和 token 解析、上下文绑定、权限校验三者强耦合,否则角色字段只是摆设,攻击者伪造 role 字段就能越权。
JWT 中间件必须手动 decode 并校验全部标准字段
webman/plugin-jwt 默认中间件只做字符串前缀匹配,不调用 JWT::decode(),也不检查 exp、nbf、iss。这意味着传一个 Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjEsImV4cCI6OTk5OTk5OTk5OX0.abc 就能绕过所有鉴权。
- 必须在自定义中间件中显式调用
JWT::decode($token, new Key($secret, 'HS256'))(注意:v6.10+ 必须传Key对象) -
exp字段必须是int类型时间戳,写成字符串如'exp' => '1716400000'会导致校验跳过 - 必须捕获四类异常并统一返回 401:
SignatureInvalidException、ExpiredException、BeforeValidException、DomainException - 提取 token 时别用
substr($auth, 7),要用正则:preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches),取$matches[1]
RBAC 权限校验不能只查数据库,必须注入请求上下文
很多实现把 user_id 从 token 解出后直接查 DB 获取 role_permissions,但没把结果挂到 $request 或全局上下文里,导致后续每个接口都要重复查一次,性能差且无法统一拦截。
Webman 2.2.0版本强化了 TCP/UDP 服务支持,优化路由组管理,并增强异步任务处理能力。结合协程与连接池技术,Webman 能轻松应对高并发场景,适用于网站、接口服务、即时通讯、物联网及游戏开发,兼具高性能、灵活扩展与稳定可靠,是多场景 PHP 服务开发的理想选择。
- 在 JWT 验证通过后,立即查出该用户所有权限标识(如
['product:edit', 'order:delete']),存入$request->attr('permissions') - 权限拦截中间件应读取
$request->attr('permissions'),而不是每次重新查库 - 避免在控制器里写
if (!in_array('user:ban', $perms)) { return json(['err' => 'no permission']); }—— 这种硬编码会失控 - 推荐用注解或路由属性标记权限点,例如在路由定义中加
'permission' => 'user:ban',中间件自动比对
密钥管理与黑名单配置极易失效,必须逐项验证
HS256 密钥一旦泄露即全盘失守;Redis 黑名单若配置错一个参数,注销就等于没注销。
- 密钥绝不能硬编码在
config/plugin/xxx/app.php,应存于runtime/keys/jwt-secret.bin,权限设为600,用file_get_contents()动态加载 - 启用黑名单时,
blacklist_ttl必须大于 token 的exp时间(如 token 过期 3600 秒,黑名单 TTL 至少设为3600 + 300) - 调用
$jwt->invalidate()才真正写入 Redis,仅 return 不触发;确认config/database.php中 redis 配置的host和port与插件配置完全一致 - 多环境共用 Redis 时,必须设置
blacklist_prefix区分,否则测试环境注销会清掉生产环境的黑名单
最常被忽略的一点:JWT payload 里只放 user_id 和 role 是不够的,RBAC 要求权限粒度落到操作级别(如 product:update:price),而不仅是资源级别(product:update)。这意味着权限数据必须支持嵌套结构或路径通配,且校验逻辑要能解析冒号分隔的权限表达式——这点几乎没人做,但外贸、SaaS 类系统恰恰最需要它。










