API Authentication (Passport) 初体验
laravel的api路由默认写了一个api
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
如果直接访问 /api/user 会重定向到登录页,已登录的也不会正常显示需要的数据,这是因为需要api授权认证才能正常访问。
为了让服务器支持API授权,体验了一把Passport OAuth 认证,把初次使用这个的过程整理记录一下,也给其它初学者一些经验。
正常的oauth授权流程应该是这样:
(A)用户访问客户端,后者将前者导向认证服务器。
(B)用户选择是否给予客户端授权。
(C)假设用户给予授权,认证服务器将用户导向客户端事先指定的"重定向URI"(redirection URI),同时附上一个授权码。
(D)客户端收到授权码,附上早先的"重定向URI",向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。
(E)认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。
从流程可知oauth授权是需要客户端和服务端二个网站,这里只使用了一个网站:laravel.test
,没有使用二个网站来模拟发送请求和授权,基本自己写的路由都是客户端的,服务端不用写啥。
安装
这个完全根据说明文档操作就行,没有任何难度,应该也不会出现任何意外。
composer require laravel/passport
php artisan migrate
php artisan passport:install
安装完成,数据库会生成几张 oauth 前缀的数据表,在 storage
目录下生成 oauth-private.key
和 oauth-public.key
二个文件,同时会生成二条 oauth client 数据。
前端快速上手
为了方便体验,服务端用户认证系统这里就直接用框架自带的,先安装上:
php artisan make:auth
php artisan migrate
前端使用到 Vue 组件:
php artisan vendor:publish --tag=passport-components
当组件被发布后,按文档在 resources/assets/js/app.js
文件中注册它们,这里我们把认证管理的三个 Vue 组件放到用户认证系统自带的 home.blade.php
中。
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">Dashboard</div>
<div class="card-body">
@if (session('status'))
<div class="alert alert-success" role="alert">
{{ session('status') }}
</div>
@endif
<passport-clients></passport-clients>
<passport-authorized-clients></passport-authorized-clients>
<passport-personal-access-tokens></passport-personal-access-tokens>
</div>
</div>
</div>
</div>
</div>
@endsection
我们要配置好前端环境,直接 yarn
安装前端组件,然后 npm run dev
。
注册一个用户登录看看:
配置
发放令牌有指令或客户端两种方式,我们已经使用 vue 组件快速建了客户端,直接点 Create New Client
来自己建个。
请求令牌
向服务端应用程序的 /oauth/authorize
路由发出请求,网址参数如下:
这里也按文档写一个路由,然后访问 http://laravel.test/redirect 请求令牌:
Route::get('/redirect', function () {
$query = http_build_query([
'client_id' => '3',
'redirect_uri' => 'http://laravel.test/callback',
'response_type' => 'code',
'scope' => '',
]);
return redirect('http://laravel.test/oauth/authorize?'.$query);
});
第一次请求时会提示是否授权:
确定授权后,服务端会重定向到回调网址,并传回授权码code。
将授权码转换为访问令牌
文档中是直接在回调路由中使用授权码,换token,这一步需要使用到 client_Secret
:
Route::get('/callback', function (\Illuminate\Http\Request $request) {
$http = new GuzzleHttp\Client;
$response = $http->post('http://laravel.test/oauth/token', [
'form_params' => [
'grant_type' => 'authorization_code',
'client_id' => '3',
'client_secret' => 'SlxvmfrYl9cRmJpsbojrksfMw8VHUhsZgEpfoc2l',
'redirect_uri' => 'http://laravel.test/callback',
'code' => $request->code,
],
]);
return json_decode((string)$response->getBody(), true);
});
使用 id 、secret、code等换到token:
现在拿到token了,我们再来访问/api/user试试,写个路由用token向服务端请求数据:
Route::get('/api-test', function (){
$client = new GuzzleHttp\Client;
$accessToken = "eyJ0eXAiOiJKV1QiLCJhbG*******6cbwIlrI";
$response = $client->request('GET', 'http://laravel.test/api/user', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer '.$accessToken,
],
]);
return json_decode((string)$response->getBody(), true);
});
客户端访问 http://laravel.test/api-test 试试,正常返回结果啦~
文档中获取授权的token有4种模式,结合这篇文档应该能更好的理解:
http://www.ruanyifeng.com/blog/2014/05/oau...
除了密码授权令牌和直接生成个人Token外,其它授权模式都需要用户登录确定授权。关于直接生成个人令牌的方式,注意图中有一个 Personal Access Tokens
,在客户端直接生成个人Token(不足的是不能设置scope权限范围),但可以直接使用,不需要用授权码换。
为了区分,这里换一个用户登录,然后直接生成Token:
用这个token再授权访问 /api/user
试试:
正常取得用户资料,完美~
在流程测试中以下网址是客户端请求方的,其它全是服务端的。
http://laravel.test/redirect 生成请求授权码的链接用
http://laravel.test/callback 请求回调网址,用来把授权码换成Token令牌
http://laravel.test/api-test 身份验证并请求服务端api(/api/user)的数据
服务端认证路由全部是Passport::routes();
注册的,具体路由可以看 vendor/laravel/passport/src/RouteRegistrar.php
其他功能这里就不演示了,只能说很好很强大~
本作品采用《CC 协议》,转载必须注明作者和本文链接