rainlee/think-auth

ThinkPHP6.0框架认证扩展

v1.0.0 2022-04-14 09:51 UTC

This package is auto-updated.

Last update: 2025-07-20 10:01:34 UTC


README

基于 ThinkPHP6 的用户认证扩展

本扩展包含 session 和 jwt 登录认证以及 auth 权限认证功能<br/> php>=7.4

安装

$ composer require rainlee/think-auth

配置

认证扩展配置 auth.php

return [
    'default' => 'web',
    'app_key' => env('app.app_key'),  // cookie加密使用
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'user'
        ],
        'api' => [
            'driver' => 'jwt',
            'provider' => 'user',
            'ignored'  => [ // 无需登录认证的节点
                'auth:login'
            ],
            'payload'  => [ // jwt荷载(Payload)部分存入的数据字段名,driver为jwt时有效,设置不存在则默认为主键
                'id',
                'username'
            ]
        ],
        'admin' => [
            'driver' => 'session',
            'provider' => 'admin',
            'policies' => 'admin',
            'ignored'  => [ // 无需登录认证的节点
                'auth:login'
            ],
        ]
    ],

    'providers' => [
        'user' => [
            'driver' => 'model',
            'model' => app\admin\model\Users::class,  // 模型需要继承 rainlee\auth\UserModel 模型
        ],
        'admin' => [
            'driver' => 'database',
            'table'  => 'users',
            'connection' => 'mysql', // database配置文件数据库链接名忽略为默认数据库链接
            'validate_pass' => 'md5' // 密码验证方式,默认password_verify
        ]
    ],

    'policies' => [ // 权限认证策略
        'admin' => [
            'auth_on'     => true,          // 认证开关
            'type'        => 1,
            'super_admin' => 1,  // 超级管理员id
            'groups'      => 'think_auth_group', //用户组数据表名
            'group_rule'  => 'think_auth_group_rule', // 用户组权限节点关联表
            'rules'       => 'think_auth_rule', //权限规则表
            'ignored'     => [  // 无需认证的节点

            ]
        ]
    ]
];

jwt 配置

return [
    'default' => 'admin', //默认场景
    'guards' => [
        'api' => [
            'unique_index'  => 'id', // 唯一索引字段名
            'signer_key'    => env('app.app_key'), // 密钥
            'effective_at'  => 0, // 生成后多久生效,默认生成后直接使用
            'expires_at'    => 7200, // Token有效期(秒
            'refresh_ttL'   => 7200,
            'signer'        => 'Lcobucci\JWT\Signer\Hmac\Sha256', // 加密算法
            'token_mode'    => ['header', 'cookie', 'param'], // 获取 Token 方式,数组靠前值优先
            'iss'           => '',
            'aud'           => '',
            'verify_ip'     => true  // 验证IP
        ],
        'admin' => [
            'unique_index'  => 'uid', // 唯一索引字段名
            'signer_key'    => env('app.app_key'), // 密钥
            'effective_at'  => 0, // 生成后多久生效,默认生成后直接使用
            'expires_at'    => 3600, // Token有效期(秒
            'refresh_ttL'   => 7200,
            'signer'        => 'Lcobucci\JWT\Signer\Hmac\Sha256', // 加密算法
            'token_mode'    => ['header', 'cookie', 'param'], // 获取 Token 方式,数组靠前值优先
            'iss'           => '',
            'aud'           => '',
            'verify_ip'     => false  // 验证IP
        ]
    ]
];

数据表

-- ----------------------------
-- sys_users 用户表
-- ----------------------------
DROP TABLE IF EXISTS `sys_users`;
CREATE TABLE `sys_users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `email` varchar(80) NOT NULL COMMENT '用户邮箱',
  `mobile` char(11) NOT NULL COMMENT '手机号',
  `password` varchar(255) NOT NULL COMMENT '用户密码',
  `username` varchar(15) NOT NULL DEFAULT '' COMMENT '用户名',
  `group_ids` varchar(255) NOT NULL DEFAULT '' COMMENT '用户组',
  `remember_token` char(60) DEFAULT NULL COMMENT '记住我',
  `last_login_ip` int(11) DEFAULT '0' COMMENT '最后登录IP',
  `last_login_time` int(11) DEFAULT '0' COMMENT '最后登录时间',
  `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态(1:正常,0:禁用)',
  `create_at` int(11) NOT NULL COMMENT '创建时间',
  `delete_at` int(11) DEFAULT NULL COMMENT '删除时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `email` (`email`),
  UNIQUE KEY `mobile` (`mobile`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
-- ----------------------------
-- sys_auth_rules,规则表,
-- id:主键,node:规则唯一标识(就是常见的路由列表,如:admin/index/index), title:规则中文名称,例如添加商品 status 状态:为1正常,为0禁用,condition:规则表达式,为空表示存在就验证,不为空表示按照条件验证
-- ----------------------------
 DROP TABLE IF EXISTS `sys_auth_rules`;
CREATE TABLE `sys_auth_rules` (
  `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  `pid` int(11) NOT NULL DEFAULT '0' COMMENT '父节点索引',
  `title` char(20) NOT NULL DEFAULT '' COMMENT '标题',
  `node` char(80) NOT NULL DEFAULT '' COMMENT '权限标识',
  `type` tinyint(1) NOT NULL DEFAULT '1' COMMENT '类型(0:目录,1:菜单,2:按钮)',
  `condition` char(100) NOT NULL DEFAULT '' COMMENT '认证条件',
  `name` varchar(80) NOT NULL DEFAULT '' COMMENT '路由名称',
  `path` varchar(255) NOT NULL DEFAULT '' COMMENT '路由标识',
  `component` varchar(255) NOT NULL DEFAULT '' COMMENT '组件路径',
  `icon` varchar(255) NOT NULL COMMENT '图标',
  `is_url` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否超链接',
  `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态(0:禁用,1:正常)',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='权限规则表';
-- ----------------------------
-- sys_auth_groups 用户组表,
-- id:主键, title:用户组中文名称, rules:用户组拥有的规则id, 多个规则","隔开,status 状态:为1正常,为0禁用
-- ----------------------------
DROP TABLE IF EXISTS `sys_auth_groups`;
CREATE TABLE `sys_auth_groups` (
  `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  `title` char(100) NOT NULL DEFAULT '' COMMENT '角色名',
  `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态(1:正常,0:禁用)',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='角色组表';
-- ----------------------------
-- sys_auth_group_rule 用户组权限节点关联表
-- gid:用户组ID,rule_id:权限节点ID
-- ----------------------------
DROP TABLE IF EXISTS `sys_auth_group_rule`;
CREATE TABLE `sys_auth_group_rule` (
  `gid` mediumint(8) unsigned NOT NULL COMMENT '角色索引',
  `rule_id` mediumint(8) unsigned NOT NULL COMMENT '权限索引',
  UNIQUE KEY `gid_rule_id` (`gid`,`rule_id`),
  KEY `gid` (`gid`),
  KEY `rule_id` (`rule_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='角色权限关联表';

用法示例

登录认证

use rainlee\auth\facade\Auth;
// 通过账号密码登录
// jwt模式下登录后会返回token字符串
$token = Auth::attempt(['email' => 'rainlee1990@yeah.ent', 'password' => '123456']);

// 通过id登录
Auth::attemptById(1);

// 指定守卫者登录
Auth::guard('admin')->attempt(['email' => 'rainlee1990@yeah.ent', 'password' => '123456']);

// 验证登录
Auth::check();
// 验证节点是否无需认证
Auth::isIgnoredNode($node);

// 获取登录用户信息
Auth::user();

// 退出登录(session模式下有效)
Auth::logout();

权限认证

/**
 * 权限认证类
 * 功能特性:
 * 1,是对规则进行认证,不是对节点进行认证。用户可以把节点当作规则名称实现对节点进行认证。
 *    Auth::authorization()->check('规则名称','认证方式(默认为url认证)')
 * 2,可以同时对多条规则进行认证,并设置多条规则的关系(or或者and)
 *    Auth::authorization()->check('规则1,规则2','认证方式(默认为url认证)','and')
 *    第三个参数为and时表示,用户需要同时具有规则1和规则2的权限。
 *    当第三个参数为or时,表示用户值需要具备其中一个条件即可。默认为or
 * 3,支持规则表达式。
 *    在 sys_auth_rules 表中定义一条规则时,如果type为1, condition字段就可以定义规则表达式。
 *    如定义{score}>5  and {score}<100  表示用户的分数在5-100之间时这条规则才会通过。
 */

示例

use rainlee\auth\facade\Auth;
// 认证节点
$controller = array_map('parse_name', explode('.', $request->controller()));
$node = implode(':', $controller) . ':' . parse_name($request->action());
// 权限认证
$auth = Auth::guard('admin');
if ($auth->authorization() && !$auth->authorization()->check($node, 'node')) {
    return json([
        'errcode' => 4014,
        'message' => 'NoAccess'
    ]);
}

// 获取用户所有权限节点
$rules = Auth::authorization()->getRules();

Auth 认证,一个用户可以属于多个用户组。 比如我们对 show_button 这个规则进行认证, 用户 A 同时属于 用户组 1 和用户组 2 两个用户组 , 用户组 1 没有 show_button 规则权限, 但如果用户组 2 有 show_button 规则权限,则一样会权限认证通过。

Auth 类还可以按用户属性进行判断权限, 比如 按照用户积分进行判断, 假设我们的用户表 (sys_users) 有字段 score 记录了用户积分。 我在规则表添加规则时,定义规则表的 condition 字段,condition 字段是规则条件,默认为空 表示没有附加条件,用户组中只有规则 就通过认证。 如果定义了 condition 字段,用户组中有规则不一定能通过认证,程序还会判断是否满足附加条件。 比如我们添加几条规则:

node 字段:grade1 condition 字段:{score}<100<br/> node 字段:grade2 condition 字段:{score}>100 and {score}<200<br/> node 字段:grade3 condition 字段:{score}>200 and {score}<300

这里 {score} 表示 sys_users 表 中字段 score 的值。 那么这时候

Auth::authorization()->check('grade1') 是判断用户积分是不是 0-100<br/> Auth::authorization()->check('grade2') 判断用户积分是不是在 100-200<br/> Auth::authorization()->check('grade3') 判断用户积分是不是在 200-300