2020-08-14 16:02:50
围观(8490)
一般后台都是使用 RBAC 权限管理。 例如 Laravel-admin 也是使用了 RBAC 权限管理。
RBAC 其实就是给每个用户添加一个或多个角色身份,每个角色身份拥有很多个权限,操作时验证用户的角色权限是否含有当前操作的权限。
创建数据库
数据表如下:

每张表的字段如下:

配置 Laravel
安装文档可以看这个: https://learnku.com/docs/laravel/7.x/installation/7447 本文就不说安装了。
安装完成后 打开 .env 文件。 将数据库配置填写进去:
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=rbac DB_USERNAME=root DB_PASSWORD=root
创建模型
在项目根目录依次执行命令:
php artisan make:model Model/Auth php artisan make:model Model/RoleAuth php artisan make:model Model/Role php artisan make:model Model/UserRole php artisan make:model Model/User
创建首个后台管理员
使用命令创建控制器:
php artisan make:controller Admin/AdminCreateController
写入一个 create 方法:
public function create()
{
$email = '123456@qq.com';
$password = Hash::make('123456');
$model_user = new User();
$row_user = $model_user->getDefaultAdmin($email);
if ($row_user) {
// 更新
$row_user->password = $password;
return $row_user->save();
}
// 创建
$model_user->name = $email;
$model_user->email = $email;
$model_user->password = $password;
$model_user->role = User::ROLE_ADMIN;
return $model_user->save();
}控制器需要引入:
use Illuminate\Support\Facades\Hash; use App\Model\User;
User 模型里面有一个 getDefaultAdmin 方法:
public function getDefaultAdmin($email = '123456@qq.com')
{
return $this->where('email', $email)
->where('role', self::ROLE_ADMIN)
->first();
}模型里面的常量:
const ROLE_USER = 0; // 普通用户 const ROLE_ADMIN = 1; // 管理员
写入路由:
Route::get('create_admin', 'Admin\AdminCreateController@create');使用域名/create_admin访问。 页面上会显示一个 “1” 再看看数据库,已经有刚才创建的管理员了:

后台登录
随便写一个登录的前端页面(views/admin/login.blade.php):
<!DOCTYPE html>
<html>
<head>
<title>不败君 RBAC 登录</title>
</head>
<body>
<form action="{{ route('admin_login') }}" method="POST">
@csrf
<input type="text" name="email" placeholder="邮箱">
<input type="password" name="password" placeholder="密码">
<input type="submit" value="登 录">
</form>
</body>
</html>创建登录控制器:
php artisan make:controller Admin/AdminLoginController
写入路由:
Route::get('login', 'Admin\AdminLoginController@index')->name('admin_login_index');
Route::post('login', 'Admin\AdminLoginController@login')->name('admin_login');写入两个方法:
public function index()
{
if ($request->session()->get('admin.user.id')) {
return redirect()->route('admin_index');
}
return view('admin.login');
}
public function login(Request $request)
{
$input = $request->all();
$validator = Validator::make($input, [
'email' => 'required|email|max:128',
'password' => 'required|min:3',
]);
if ($validator->fails()) {
return response()->json(['code' => 100, 'msg' => $validator->errors()->first()]);
}
// 查询邮箱对应的用户
$model_user = new User();
$row_user = $model_user->getUserByEmail($input['email']);
$msg_error = '账号或密码错误';
if (!$row_user) {
return response()->json(['code' => 101, 'msg' => $msg_error]);
}
// 校验密码
if (Hash::check($input['password'], $row_user['password'])) {
// 密码正确
$request->session()->push('admin.user.id', $row_user['id']);
$request->session()->push('admin.user.role', $row_user['role']);
return redirect()->route('admin_index');
}
return response()->json(['code' => 101, 'msg' => $msg_error]);
}login 方法用了表单验证如果不懂可以看 Laravel 的文档。
中间件
需要创建一个中间件鉴权后台用户登录状态。
php artisan make:middleware CheckAdminLogin
中间件写入:
public function handle($request, Closure $next)
{
$user_id = $request->session()->get('admin.user.id')[0];
if (!$user_id) {
return redirect()->route('admin_login_index');
}
return $next($request);
}注册中间件可以看看官方文档,本文就不写了。
接着写一个路由群组,将后台全部需要登录才能看到的路由都写进这个群组:
Route::middleware(['check_admin_login'])->namespace('Admin')->prefix('admin')->group(function () {
Route::get('/', 'IndexController@index')->name('admin_index');
});创建后台页面的控制器:
php artisan make:controller Admin/IndexController
在 IndexController 写入方法:
public function index()
{
return '后台首页';
}此时后台登录已经完成。
验证系统管理员权限
由于是系统管理员才能管理角色 / 用户 / 权限 / 以及给用户角色分配权限等等的功能,所以还需要加一个中间件验证是否为系统管理员。
创建中间件:
php artisan make:middleware CheckAdminRole
在中间件写入方法:
public function handle($request, Closure $next)
{
$role = $request->session()->get('admin.user.role')[0];
if ($role !== User::ROLE_ADMIN) {
return redirect()->route('admin_login_index');
}
return $next($request);
}角色管理
角色管理就是个简单的增删查改,本文就不贴角色管理的代码了。
主要就是在中间件路由群组 check_admin_role 中写入路由:
Route::resource('role', RoleController::class);现在的路由是这样的:
Route::middleware(['check_admin_login'])->namespace('Admin')->prefix('admin')->group(function () {
Route::get('/', 'IndexController@index')->name('admin_index');
Route::middleware(['check_admin_role'])->group(function () {
Route::resource('role', RoleController::class); // 角色管理增删查改的控制器
});
});博主实现的列表:

添加:

样式丑什么的就不要管了~~~
用户管理
和角色管理一样,写一个用户的增删查改即可。
修改路由:
Route::middleware(['check_admin_login'])->namespace('Admin')->prefix('admin')->group(function () {
Route::get('/', 'IndexController@index')->name('admin_index');
Route::middleware(['check_admin_role'])->group(function () {
Route::resource('role', RoleController::class); // 角色管理增删查改的控制器
Route::resource('user', UserController::class); // 用户管理增删查改的控制器 就是加了这个而已
});
});实现出来的效果和角色的差不多。
权限管理
和上面两个管理一样,还是增删查改的功能。
写好之后路由继续增加:
Route::resource('auth', AuthController::class);用户绑定角色
前面已经写好了用户管理的,所以这个是要修改原来的代码。
要实现的功能:给用户选择某些角色绑定后存储数据到 user_roles 表,存储前需要清空一次该用户已存在 user_roles 表的记录,不然会重复。
先要在前面开发好的用户管理和角色管理中添加一些角色和用户。
角色:

用户:

经过修改后的用户列表:

绑定角色的功能:

角色添加权限
和用户绑定角色一样,需要修改之前写的角色管理,选择角色后跳转页面,页面提供选择权限 ( auths 表 ) 并存储,存储到 role_auths 表。
修改完成后的效果:

中间件权限验证
到这一步就是重点了,前面写了这么多无非就是为了中间件可以鉴权。
修改中间件 CheckAdminLogin :
public function handle($request, Closure $next)
{
$user_id = $request->session()->get('admin.user.id')[0];
if (!$user_id) {
return redirect()->route('admin_login_index');
}
// 鉴权
// 先获取该用户对应的全部角色
$model_user_role = new UserRole();
$rows_user_role = $model_user_role->selectByUserIds([$user_id]);
// 根据角色获取全部权限
$array_role_id = array_column($rows_user_role->toArray(), 'role_id');
$model_role_auth = new RoleAuth();
$rows_role_auth = $model_role_auth->selectByRoleIds($array_role_id);
$array_auth_id = array_column($rows_role_auth->toArray(), 'auth_id');
$model_auth = new Auth();
$rows_auth = $model_auth->selectByIds($array_auth_id);
// 组装全部 URL
$map_url = [];
foreach ($rows_auth as $row_auth) {
$urls = array_column($row_auth['urls']);
foreach ($urls as $url) {
$map_url[$url] = $url;
}
}
$uri = $request->route()->uri;
$role = $request->session()->get('admin.user.role')[0];
if ($role !== User::ROLE_ADMIN && !isset($map_url[$uri])) {
exit('无权限访问');
}
return $next($request);
}其实到这一步,发现之前写了两个中间件,第二个中间件 CheckAdminRole 是可以不用的...
测试
弄一个简单的后台首页,IndexContorller 控制器:
public function index()
{
$html = '<h1>后台首页</h1>';
$html .= '<div><a href="' . route('role.index') . '">角色管理</a></div>';
$html .= '<div><a href="' . route('user.index') . '">用户管理</a></div>';
$html .= '<div><a href="' . route('auth.index') . '">权限管理</a></div>';
return $html;
}给测试用户添加一个角色:

使用这个账号登录后台:

给这个角色添加后台首页的权限后刷新:

总结
路由最好不写资源路由,不然后台添加权限 URL 的时候,就不能细分某些权限了。
菜单也是可以完全动态形式控制的,本文仅讲解 RBAC 权限管理的实现方法,代码写得比较烂,可以优化的空间很大。
本文写的代码:https://pan.baidu.com/s/1eWkdnbrlw9v8lP9Luym9lA
提取码:fvr5
本文地址 : bubaijun.com/page.php?id=205
版权声明 : 未经允许禁止转载!
上一篇文章: 原生PHP使用GD库压缩图片及增加水印
下一篇文章: 使用VBOX搭建一个本地Linux服务器