Laravel 利用 doctrine/annotations 在注解中实现角色权限控制
基本术语
项目中基于常见的角色和权限方式实现权限控制,下面介绍一些术语。
- 用户
- 登录使用系统的自然人
- 角色
- 系统中用户的身份,比如管理员,普通用户,不同的角色权限不同,同一用户可以有任意多个角色
- 权限
- 用户行为,具体为做某件事的能力,有权限即能做此事。一个角色可以有任意项权限,拥有多个角色的用户即拥有这些所有权限的并集。
简单用法
本文实现的权限控制只要是针对API进行权限控制,控制力度分3级。具体的实现方法是在控制器的方法注释中添加注解。注解会在 Laravel 的中间件中被读取,然后判断是否有权限。没有权限则会返回统一的报错。
以下是三级力度的控制方法。
- 公开API,未填写权限注解的是公开API,无需登录即可访问
1
2
3
4
5
6
7
8
9/**
* 获取icp备案号
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function icp(Request $request)
{
...
} - 登录后才可访问的 API,@Permission()注解指定当前路由需要登录后才可访问
1
2
3
4
5
6
7
8
9
10/**
* 省
* @Permission()
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function states(Request $request)
{
...
} - 登录用户必须具有特定权限才可访问,当前路由要求登录用户必须具有add_customer权限。
1
2
3
4
5
6
7
8
9
10
11/**
* 新建客户
* @Permission(action="add_customer")
* @param Request $request
* @return \Illuminate\Http\JsonResponse
* @throws \Illuminate\Validation\ValidationException
*/
public function add(Request $request)
{
...
}
表结构
1 | /* |
核心实现
Laravel 提供了中间件的概念,可以为统一为某些url添加前置或后置函数处理。本文使用了前置中间件。
引入 doctrine/annotations 依赖
composer require doctrine/annotations ^1.10
创建前置中间件
`php artisan make:middleware AnnotationCheck在handle 函数中添加处理逻辑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30public function handle($request, Closure $next)
{
$route = $request->route();
if (empty($route)) {
return $this->respond(500, '路由信息为空');
}
$controller = $route->getController();
try {
// 反射获取目标控制器对象
$class = new \ReflectionClass($controller);
// 反射获取目标控制器的目标方法
$method = $class->getMethod($route->getActionMethod());
AnnotationRegistry::registerFile(app_path('Annotations/Permission.php'));
$reader = new AnnotationReader();
foreach ($reader->getMethodAnnotations($method) as $annotation) {
if ($annotation instanceof Permission) {
if (!auth()->check()) {
return $this->respond(401, '用户未登录');
}
if (strlen($annotation->action) == 0) {
return $next($request);
}
return auth()->user()->can($annotation->action) ? $next($request) : $this->respond(403, '权限不足');
}
}
return $next($request);
} catch (\Exception $e) {
return $this->respond(500, $e->getMessage());
}
}在
app\Http\Kernel.php
中的$routeMiddleware
数组中添加注解中间件的注册,这样就可以在路由配置文件中使用此中间件了。1
2
3
4
5protected $routeMiddleware = [
...
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'annotation' => AnnotationCheck::class, // 添加这一行
];在
routes/api.php
中使用此中间件1
2
3
4Route::prefix('admin')->namespace('Admin')->middleware('annotation')->group(function () {
Route::post('user/resetPassword', 'UserController@resetPassword');
// 省略其它路由
}
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 一个弱小的后端!
评论