wuguofeng / webman-bouncer
Bouncer RBAC (roles & abilities) plugin for webman. Adapts silber/bouncer to webman's long-running process model with per-request state isolation.
Requires
- php: ^8.2
- illuminate/container: ^11.0 || ^12.0 || ^13.0
- illuminate/database: ^11.0 || ^12.0 || ^13.0
- silber/bouncer: ^1.0.2
- workerman/webman-framework: ^2.1
Requires (Dev)
- phpunit/phpunit: ^11.5
- symfony/console: ^7.1
- webman/cache: ^2.1
- webman/redis: ^2.1
Suggests
- webman/cache: Required for cross-request cache stores (config 'cache' => 'file' | 'redis' | ...)
- webman/database: Recommended: enables connection pooling for Eloquent in long-running processes
This package is not auto-updated.
Last update: 2026-08-07 06:36:33 UTC
README
Silber\Bouncer(RBAC 角色与能力)的 webman 插件。 将 bouncer 适配到 webman 的长驻进程模型:每个请求独立的 Bouncer 实例(独立的剪贴板与缓存), 避免进程级静态状态串号与权限缓存过期问题。
特性
- 100% 复用
silber/bouncer原版 API:Bouncer::allow()/assign()/is()/can()/forbid()、模型 trait$user->can()/$user->isAn()。 - 每请求重建实例(
request缓存策略,ArrayStore),改权限即刻生效,无需手动refresh()。 - 多租户 scope 支持:
scope_resolver每请求重置,防止租户串号。 - 自动初始化 Illuminate 容器 + Eloquent(优先复用
webman/database的连接池)。 - 提供
php webman bouncer:install一键建表。
安装
# 项目根目录
composer require wuguofeng/webman-bouncer -W
安装后插件配置自动拷贝到 config/plugin/wuguofeng/webman-bouncer/。
配置
编辑 config/plugin/wuguofeng/webman-bouncer/app.php:
return [ 'enable' => true, 'user_model' => 'app\model\User', // 你的 Eloquent 用户模型 'user_resolver' => fn () => session()->get('user'), // 每请求当前用户,匿名返回 null 'cache' => 'request', // 'request' | 'none' | webman/cache store 名 'scope_resolver'=> null, // 多租户:返回租户 id,或 null 关闭 'tables' => [], ];
缓存策略(cache)
| 值 | 说明 |
|---|---|
'request'(默认) |
每请求独立内存缓存(ArrayStore),改动即刻生效,无需手动刷新。推荐日常使用 |
'none' |
完全禁用缓存,每次校验都查库 |
store 名(如 'file'、'redis') |
跨请求/跨进程持久缓存,复用你项目的 config/cache.php(webman/cache)里的 store |
使用跨请求缓存前先安装并配置 webman/cache:
composer require webman/cache # redis store 还需: composer require webman/redis(并配置 config/redis.php) # config/cache.php 中定义 stores,例如: # 'file' => ['driver' => 'file', 'path' => runtime_path('cache')], # 'redis' => ['driver' => 'redis', 'connection' => 'default'],
跨请求缓存适合权限数据量大、校验频繁、变更低频的场景(首次校验少查库、后续全部命中缓存)。 代价是权限改动不即时生效,变更后需要手动失效:
use Webman\Bouncer\Bouncer; Bouncer::refresh($user); // 只清该用户的缓存(推荐,改动哪个用户就清哪个) Bouncer::refresh(); // 清全部缓存(用户量大时较慢,慎用)
用户模型:
<?php namespace app\model; use Silber\Bouncer\Database\Concerns\Authorizable; use Silber\Bouncer\Database\HasRolesAndAbilities; use support\Model; class User extends Model { use HasRolesAndAbilities; use Authorizable; }
建表:
php webman bouncer:install
使用
use Webman\Bouncer\Bouncer; // 授权(幂等) Bouncer::allow('admin')->to('edit-post'); Bouncer::assign('admin')->to($user); Bouncer::allow($user)->toOwn(Post::class); // 校验(门面) Bouncer::can('edit-post'); // bool,针对当前请求用户 Bouncer::cannot('delete-post'); Bouncer::authorize('edit-post'); // 无权限抛 AuthorizationException // 校验(模型 trait,走同一每请求实例) $user->can('edit-post'); $user->isAn('admin');
中间件
config/plugin/wuguofeng/webman-bouncer/middleware.php 默认注册了 BouncerMiddleware(作用于所有请求),
保证请求处理器执行前已存在新鲜的 Bouncer 实例(trait 用法依赖它)。不需要可移除。
命令
| 命令 | 说明 |
|---|---|
php webman bouncer:install |
创建 bouncer 四张表(abilities / roles / assigned_roles / permissions) |
测试
composer test
前置:本地 MySQL(默认 127.0.0.1:3306,库 webman_bouncer_test,用户 bouncer / bouncer_pass),
可用环境变量覆盖:
| 环境变量 | 默认值 |
|---|---|
BOUNCER_TEST_DB_HOST |
127.0.0.1 |
BOUNCER_TEST_DB_PORT |
3306 |
BOUNCER_TEST_DB_NAME |
webman_bouncer_test |
BOUNCER_TEST_DB_USER |
bouncer |
BOUNCER_TEST_DB_PASS |
bouncer_pass |
BOUNCER_TEST_CACHE |
request(request | none) |
bootstrap 自动建库建表(每次运行先清空重建),并把数据库与插件配置替换为 tests/config/ 下的
fixture。测试用 support\Context 模拟请求边界(Context::destroy()),确保每请求实例、租户
scope、剪贴板等状态不在用例间串号。
工作原理
webman 是长驻进程,进程级静态状态会跨请求残留。本插件把 bouncer 的全部可变状态
(Clipboard、缓存、租户 Scope)放进每请求实例(存于 support\Context,协程安全),
启动时只做进程级一次性配置(Illuminate 容器单例、Eloquent、用户模型映射、morph map):
请求 → BouncerMiddleware → Bouncer::instance()(惰性创建,存 Context)
→ 控制器/模型使用(同一实例,请求结束随 Context 销毁)
License
MIT