2020-08-14 16:02:50
围观(7153)
一般后台都是使用 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服务器