配置后端应用
在后端应用 blog
中通过 Passport::tokensCan
定义 API 认证的令牌作用域。打开 AuthServiceProvider
服务提供者类,在 boot
方法中调用该方法,设置三个令牌作用域:
// 令牌作用域
Passport::tokensCan([
'basic-user-info' => '获取用户名、邮箱信息',
'all-user-info' => '获取用户所有信息',
'get-post-info' => '获取文章详细信息',
]);
打开 app/Http/Kernel.php
,在 $routeMiddleware
属性中引入两个中间件:
'scopes' => \Laravel\Passport\Http\Middleware\CheckScopes::class,
'scope' => \Laravel\Passport\Http\Middleware\CheckForAnyScope::class,
scopes
用于检查传入令牌作用域是否包含所有指定中间件参数,scope
用于检查传入令牌作用域是否包含任意指定中间件参数。
在 routes/api.php
中新增一个获取文章详情信息的路由,并修改路由定义如下:
Route::middleware('auth:api')->group(function () {
Route::get('/user', function (Request $request) {
$user = $request->user();
if ($user->tokenCan('all-user-info')) {
// 如果用户令牌有获取所有信息权限,返回所有用户字段
return $user;
}
// 否则返回用户名和邮箱等基本信息
return ['name' => $user->name, 'email' => $user->email];
})->middleware('scope:basic-user-info,all-user-info');
Route::get('/post/{id}', function (Request $request, $id) {
return \App\Post::find($id);
})->middleware('scopes:get-post-info');
});
第一个路由应用了 scope
中间件,要求传入令牌作用域包含 basic-user-info
或 all-user-info
任意一个即可,并且在路由闭包中根据用户具体字段获取权限进一步进行了细分;
第二个路由应用了 scopes
中间件,要求传入令牌作用域必须包含 get-post-info
,如果有多个的话,可以通过逗号分隔。
在第三方应用中测试
在第三方应用 testapp
,将配置信息修改回授权码令牌对应配置,然后在 /auth
路由对应控制器方法 LoginController@oauth
中,设置 scope
请求字段值:
public function oauth()
{
$query = http_build_query([
'client_id' => config('services.blog.appid'),
'redirect_uri' => config('services.blog.callback'),
'response_type' => 'code',
'scope' => 'all-user-info get-post-info',
]);
return redirect('http://blog.test/oauth/authorize?'.$query);
}
在本例中,为了简化处理流程,直接在第三方应用控制器方法中写死了作用域,实际场景中可以让用户自行勾选,然后通过表单传递到控制器方法。
在浏览器中访问 http://test.app/auth
通过授权码获取令牌,跳转到后端系统授权界面时会多出一段提示信息告知该授权令牌的作用域。
点击绿色的确认授权按钮后,就可在第三方应用中获取到授权令牌,与此同时,也会在后端应用数据表 oauth_access_tokens
和 oauth_auth_codes
生成的记录看到对应的 scopes
字段值。
接下来,可以通过取得的 access_token
在 Postman 中测试对后端认证接口的访问。
请求 /api/user
和 /api/post/1
都成功了。
把第三方应用 /auth
路由传递的 scope
请求字段值调整为了 basic-user-info
:
public function oauth()
{
$query = http_build_query([
'client_id' => config('services.blog.appid'),
'redirect_uri' => config('services.blog.callback'),
'response_type' => 'code',
'scope' => 'basic-user-info',
]);
return redirect('http://blog.test/oauth/authorize?'.$query);
}
再次通过 http://test.app/auth
获取令牌,令牌作用域就会发生变化。
确认授权之后,会获取到新的令牌信息,然后使用这个令牌访问用户接口,就只能取到最基本的用户字段信息,试图访问文章详情接口,则会返回 403
响应。
结语
通常会在 scope
字段传入 *
(或留空,每种令牌认证有所不同)表示获取到的令牌具备所有认证接口访问权限,但如果对安全性要求比较高的系统,则可以通过令牌作用域的方式对令牌访问权限做更细分的设置,通过 Passport 内置的脚手架,可以快速实现令牌作用域功能,非常方便。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。