欢迎访问宙启技术站
智能推送

怎么在thinkPHP5中使用Rabc实现权限管理

发布时间:2023-05-14 01:21:20

在实现一个完整的web应用时,我们通常需要一个完善的权限管理系统来保护敏感操作和数据,防止恶意攻击和误操作。其中的一个常用的解决方案就是使用Rbac(Role-based access control)模型。

在ThinkPHP5中,自带了Rbac的支持,本篇文章将介绍如何在ThinkPHP5中使用Rbac实现权限管理。

1. 数据库设计

为了实现Rbac模型,我们需要在数据库中建立多个表来存储角色、权限和用户等信息。下面是一个简单的示例表设计,实际情况下,你可能需要根据具体的业务需求来进行扩展。

角色表:

| id | name | description |

|----|--------|-------------|

| 1 | admin | 管理员 |

| 2 | member | 普通用户 |

权限表:

| id | name | description |

|----|-----------|-------------|

| 1 | add_user | 添加用户 |

| 2 | edit_user | 修改用户 |

角色权限关联表:

| id | role_id | permission_id |

|----|---------|--------------|

| 1 | 1 | 1 |

| 2 | 1 | 2 |

| 3 | 2 | 1 |

用户表:

| id | username | password |

|----|----------|----------|

| 1 | admin | 123456 |

| 2 | user1 | 123456 |

用户角色关联表:

| id | user_id | role_id |

|----|---------|---------|

| 1 | 1 | 1 |

| 2 | 2 | 2 |

2. 配置文件

在使用Rbac之前,我们需要在配置文件中添加相应的设置。打开config文件夹下的auth.php文件,并按如下方式进行设置:

'auth'         => [
    'auth_on'           => true,                 // 权限开关
    'auth_type'         => 1,                    // 认证方式,1为实时认证;2为登录认证。
    'auth_group'        => 'auth_role',          // 角色表,不包含前缀
    'auth_group_access' => 'auth_role_user',     // 用户-角色关系表,不包含前缀
    'auth_rule'         => 'auth_permission',    // 权限规则表,不包含前缀
    'auth_user'         => 'auth_user',          // 用户信息表,不包含前缀
],

其中auth_on表示是否开启权限控制,auth_type表示认证方式,如果设置为1,则每次请求都会进行实时认证,如果设置为2,则只在用户登录时进行认证。

auth_groupauth_group_accessauth_ruleauth_user是我们自己定义的表名,这些表名可以根据实际情况进行修改。

3. 模型定义

接下来,我们需要定义相应的模型。打开app/common/model文件夹,在其中新建Role.php、Permission.php、User.php、UserRole.php四个模型。

其中Role代表角色,Permission代表权限,User代表用户,UserRole代表用户和角色的关系。

Role.php

<?php

namespace app\common\model;

use think\Model;

class Role extends Model
{
    protected $table = 'auth_role';

    public function permissions()
    {
        return $this->belongsToMany('Permission', 'auth_role_permission', 'role_id', 'permission_id');
    }

    public function users()
    {
        return $this->belongsToMany('User', 'auth_role_user', 'role_id', 'user_id');
    }
}

Permission.php

<?php

namespace app\common\model;

use think\Model;

class Permission extends Model
{
    protected $table = 'auth_permission';

    public function roles()
    {
        return $this->belongsToMany('Role', 'auth_role_permission', 'permission_id', 'role_id');
    }
}

User.php

<?php

namespace app\common\model;

use think\Model;

class User extends Model
{
    protected $table = 'auth_user';

    public function roles()
    {
        return $this->belongsToMany('Role', 'auth_role_user', 'user_id', 'role_id');
    }

    public function getRoles()
    {
        return $this->roles()->select();
    }

    public function can($permission)
    {
        $roles = $this->getRoles();
        foreach ($roles as $role) {
            if ($role->permissions()->where(['name' => $permission])->find()) {
                return true;
            }
        }
        return false;
    }
}

UserRole.php

<?php

namespace app\common\model;

use think\Model;

class UserRole extends Model
{
    protected $table = 'auth_role_user';
}

在上面的模型中,我们用到了belongsToMany()方法建立角色和权限/用户之间的多对多关系。另外,给User模型添加了一个can()方法,用于判断用户是否具有某个权限。

4. 中间件定义

我们可以使用中间件来对请求进行拦截和验证。打开app/middleware文件夹,在其中新建Auth.php中间件。

Auth.php

<?php

namespace app\middleware;

use think\facade\Session;
use app\common\model\User;

class Auth
{
    public function handle($request, \Closure $next)
    {
        if (!Session::has('user')) {
            return redirect('/login');
        }

        $user = User::get(Session::get('user')->id);
        if (!$user || !$user->can(Request::module() . '/' . Request::controller() . '/' . Request::action())) {
            return abort(403, '无权操作!');
        }

        $request->bind('user', $user);
        return $next($request);
    }
}

在这个中间件中,我们采用了对请求进行拦截的方式,如果用户未登录则跳转到登录页面,如果用户无权操作,则返回403错误。

同时,我们把当前用户绑定到$request对象中,这样我们就可以在控制器中直接使用$request->user来访问当前用户对象。

5. 配置路由

最后,我们需要对路由进行配置,以便使用中间件进行权限控制。打开app/route/route.php文件,并按如下方式进行配置:

use app\middleware\Auth;

Route::group('', function () {
    Route::rule('user/add', 'user/add')->middleware(Auth::class);
    Route::rule('user/edit', 'user/edit')->middleware(Auth::class);
    Route::rule('user/delete', 'user/delete')->middleware(Auth::class);
})->middleware(Auth::class);

这里我们对/user/add、/user/edit、/user/delete三个路由都进行了权限控制,只有具有相应权限的用户才能访问这些路由。

到这里,我们已经完成了在ThinkPHP5中使用Rbac进行权限管理的全部内容。需要注意的是,这只是一个简单的示例,实际应用中仍需根据具体业务需求来进行进一步的扩展。