Skip to content

认证与权限

Pin 提供基于 Token 的自定义 Guard,以及围绕菜单和权限码的 Access 系统。

Guard 配置

默认 config/auth.php 会注册 pin guard 和 provider:

php
use Pin\Auth\Guard;
use Pin\Auth\UsersProvider;

return [
    'guards' => [
        Guard::NAME => [
            'driver' => Guard::NAME,
            'provider' => UsersProvider::NAME,
            'token_key' => 'token',
        ],
    ],

    'providers' => [
        UsersProvider::NAME => [
            'driver' => UsersProvider::NAME,
            'model' => env('AUTH_MODEL', App\Models\User::class),
        ],
    ],
];

请求中的 Token 解析优先级:

  1. 标准 Authorization: Bearer {token}
  2. 自定义 Header,默认 key 为 token
  3. Query 参数,默认 key 为 token

Debug 登录

非生产环境下,Guard 支持调试登录:

  • Token 是纯数字时,按用户 ID 查询。
  • Token 长度小于 30 时,按 username 查询。
  • Sanctum Token 会被跳过,不参与 Pin Token 解析。

生产环境或 Sanctum Token 不会走 Debug 登录。

生成认证 Token

Pin\Auth\Auth::token() 会返回名为 auth-token 的 TokenFactory。业务项目可以把它映射到配置中的具体 token driver。

php
use Pin\Auth\Auth;

$token = Auth::token()->encode([
    'uid' => $user->id,
], expires: 7200);

校验用户时,Guard 会解码 Token 并读取 uid

AccessUser

需要接入权限系统的用户模型实现 AccessUser

php
use Illuminate\Support\Collection;
use Pin\Auth\Access\Contracts\AccessUser;

class User extends Authenticatable implements AccessUser
{
    public function hasAllAccess(): bool
    {
        return $this->is_admin;
    }

    public function accessibleMenus(): Collection
    {
        return $this->menus;
    }
}

hasAllAccess() 返回真时,权限码列表为空数组,表示拥有全部权限。

权限中间件

权限配置默认关闭:

php
'access' => [
    'middleware' => Pin\Auth\Access\Middleware\Access::class,
    'access_provider' => Pin\Auth\Access\AccessProvider::class,
    'menu_model' => Pin\Auth\Access\Models\Menu::class,
    'enabled' => false,
    'except' => [],
],

开启后,Access 中间件会调用 Laravel Gate:

php
Gate::allows('access', $code);

未显式传入 code 时,默认使用当前路由名称。

与枚举路由配合

路由枚举可以通过 #[Access] 控制权限码:

php
use Pin\Route\Attributes\Access;

enum UserRoute: string implements Routable
{
    use InteractsWithRoute;

    case List = 'GET:/api/users';

    #[Access('users.create')]
    case Create = 'POST:/api/users';

    #[Access(false)]
    case PublicProfile = 'GET:/api/profile/public';
}
  • #[Access('users.create')] 使用指定权限码。
  • #[Access(false)] 跳过权限中间件。
  • 不声明时使用路由名称。

权限缓存

AccessProvider 会使用两层缓存:

  • Memoize:进程内缓存。
  • Laravel Cache:默认缓存 86400 秒。

清理用户权限缓存:

php
Pin\Auth\Access\AccessProvider::flushAccess($user);

菜单数据会自动补齐祖先节点、过滤禁用菜单,并按树结构排序。