laravel之passport oauth2认证之2
密码授权,顾名思义,使用帐号和密码认证来获得令牌,因此节省了授权这一步
创建一个密码授权客户端
php artisan passport:client --password
[root@localhost laravel53]# php artisan passport:client --password
What should we name the password grant client? [Laravel Password Grant Client]:
> kqapi
Password grant client created successfully.
Client ID: 14
Client Secret: 283Ms7EPcyzuuBtqr6S26YcJd8XJ0QlkkZ9jCe8T
上面生成数据库
image.png这里user_id为空,我们改完1,因为是密码令牌,所以password_client是1
请求令牌
Route::get('/auth/password', function (\Illuminate\Http\Request $request){
$http = new \GuzzleHttp\Client();
$response = $http->post('http://192.168.91.130:82/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => '14',
'client_secret' => 'XtkyWdevgTnqbVtWTd8l7ASx76VtBBuZHzlAbCvm',
'username' => '531833998@qq.com ,
'password' => '123456',
'scope' => '',
],
]);
return json_decode((string)$response->getBody(), true);
});
返回
{
"token_type": "Bearer",
"expires_in": 31536000,
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjU1MTgxNjVjZjgyMTljNTZkODFkYmIxZmZmZjU4NDJjMjkyYzFkYTkyMzVmOWJkN2EzN2I0MGY1NzdlOWJkMWI5OTc4NjY5NjVhYjExYmM4In0.eyJhdWQiOiIxNCIsImp0aSI6IjU1MTgxNjVjZjgyMTljNTZkODFkYmIxZmZmZjU4NDJjMjkyYzFkYTkyMzVmOWJkN2EzN2I0MGY1NzdlOWJkMWI5OTc4NjY5NjVhYjExYmM4IiwiaWF0IjoxNTI4Nzk0NTQ2LCJuYmYiOjE1Mjg3OTQ1NDYsImV4cCI6MTU2MDMzMDU0Niwic3ViIjoiMyIsInNjb3BlcyI6W119.rMWLL4VtSFcyJiuVtEWA0EpZDfwcDkRb7mbkrVM4LzF6bLO72Lt2SgNkG_bk9uCi8jTS3cJxPFfc-ukAjg2ogUALy0FYjq2g0XNTugrJcqoWvCg_a7DWQI6UovqqeS1AEjgKGx_T7SQp34YZUnDV9rlxogSHR6DcRoOaurGHaknL7UQTfBR5uoxnn3KI08zh9CuOYRXrvNJJYc9qj1jn4h8CI0sQN3VgMq-Iz-Bcj2FqwgKFcQwFNnpKmg8apZkL7OfWapLzNCYNP1zAPZ-12C1JLyYsH65jWqHgfVuChWShLidoEh9mpH1rQBZJshKBRPLybncowXxuVCVHYWH9LYD2tKkuMjWjoMIGMoounRg_PFmYuI0mZcJb-tWf5OXje_IjjNFXJnjNVH0AhWwmtJagEPDCqbYEU8SZuBlyXs_HBMZpzvxIZMCxRr-_63sFP0JalHPn3b9iPbwxaVtHg1wRAU7BTK5koMh5vlZ1aodzxagBjKDzNP-krR8-maYd2q7wvKeWHJIwshUUy39Q4hLMXZLTQbCYUryPgKGY7K-PNfPj1_0ETVLd85jEEBaEioW7z7eklslJwo65JK0etHNMNACp43qZEDHXFjCQ7x-XXHTb7TxOPRBP4zihYDaezNR7QJCNIW6vlJszred80dsE8ETqthU5uovoxJuwycI",
"refresh_token": "def502009609d1fb720113dae16d172e1dc87444ebc1a39abe71ec62b2572e2d1d6f37a7d25462846e7bd75884574507ce44662d0b579a0c5258074b5e17772d75ffc4347e118cf249eb474bad83cdbbd5bf61f1b841d7c38145a29fdb3de0ac9a3a0411e93f05382804cfeab289aa814040c9208cdb8771c918253b12825ece3810c6e165af4796f2b5fd0ed34ada4a1ccc953823e3a16f89e71bc8d424b456e8ef078a1fa8c710da63734abfdb82ecbce4238c530cc3ceac0e67a2e8ec40b5a633133c5a8b3e048eb6c484140024ba337883f0e99158b7b901ee7e5f34ce9d2c696310ac160295e14d1cb003f64d63dccaadfecdc4107e8bc94c2c73f77676e136c36276ac8f0ab4c5af81af783eb3daa124c01248d9a019c31797fa37c53405722cbba1025141c3a90dc9234b726c7148dd336914f631ee0254b9dab906fc870f4e26fd1378412f394248902b7b2ab76c7a140e0957f497c8e1510eeb7a6c63e9"
}
这里写入到数据库表oauth_access_token,oauth_refresh_tokens
隐式授权令牌
隐式授权和授权码授权有点相似,不过,无需获取授权码,令牌就会返回给客户端
在 AuthServiceProvider 中调用 enableImplicitGrant 方法即可:
目前测试,不成功,后续再补
image.png
帐号和密码也不提示错误以否,一直弹出这个
客户端凭证授权令牌
客户端凭证授权适用于机器对机器的认证
Route::get('/client_credentials', function () {
$guzzle = new GuzzleHttp\Client;
$response = $guzzle->post('http://192.168.91.130:82/oauth/token', [
'form_params' => [
'grant_type' => 'client_credentials',
'client_id' => '14',
'client_secret' => '283Ms7EPcyzuuBtqr6S26YcJd8XJ0QlkkZ9jCe8T',
'scope' => '*',
],
]);
return json_decode((string) $response->getBody(), true);
});
返回
{
"token_type": "Bearer",
"expires_in": 31536000,
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjJiZjdmN2QyNzFkZDZjODhiY2IwMzgxOWRkODk3MWFkZjUwN2QwZWUxYzdhZGYwNjg1NTI3OWM4NjQ0MzJlMWUxMmIwYzRhMjgzNmQ4NDA3In0.eyJhdWQiOiIxNCIsImp0aSI6IjJiZjdmN2QyNzFkZDZjODhiY2IwMzgxOWRkODk3MWFkZjUwN2QwZWUxYzdhZGYwNjg1NTI3OWM4NjQ0MzJlMWUxMmIwYzRhMjgzNmQ4NDA3IiwiaWF0IjoxNTI4Nzk1NjkwLCJuYmYiOjE1Mjg3OTU2OTAsImV4cCI6MTU2MDMzMTY5MCwic3ViIjoiIiwic2NvcGVzIjpbXX0.PZ-qvAz8x9hJRtuupJVHHiwBZ3Sq2aBaBKCsPyQTZmGjQ3h4Oy5JzWdvXms4kzcdEhq_MyFE601A61nSvUqDeFtlEk0maHjyg1FBj7xKSwRCWuV12BCAiGSXXCLlk_siSzF1uJueWL82aOVRyM6p-HueCH1XCENXL1xVS4q39hqEDXiRSKtMnsuzAnpz5Xb4f9UyRNAXruY4LzwxBpMSFSSmRFQ1JQJ4Y1vTxr_uzuRp2qWEGChQHQDzLcaydDjbBt3UhoZ39vSgYuWGUj9G2ObX1zM86VzZk2CYKic38UbUZWaSLVJ4sd-3XqqmxGnekFYG_DUpM4K03iOeLgsspiZLLv4EBuuhJ-Z5YzPR-ojiFC0N4R6c9aAg103oF6geF5ifmK15OrtKFd0mOBSM1vV6dc0vEmJogjvqP_r2I0xYd9qAYCI2AVY0rGB2KvssXDDg2uYjQhEXukMqNw3-Tzhr19ff2jN4ERlHsnHmG8oTf_MyOivfS-3IHUyuvJTeEeZTImhMeoyqP5Rb5WaRPB9B8lbxGdVbwO_XBp0nzJTP4s2n7X6UX4iDp4zfhQxKfWJQ98IyQdzVeM4fZpMaMie1fVIGWyogZvQCu7Gy2enRhLtpgNQXA4XMGeUBawelhKkzJWYcdtZ8WS9KvN7m1KU-dWCr5uvbHPaN5Mw9fZ4"
}
这里是没有刷新的哦
私人访问令牌
用户可能想要颁发访问令牌给自己而不走典型的授权码重定向流程
创建一个私人访问客户端
[root@localhost laravel53]# php artisan passport:client --personal
What should we name the personal access client? [Laravel Personal Access Client]:
> kongwiwork
Personal access client created successfully.
Client ID: 15
Client Secret: 0kdp9zuu9c9sgt9qojgxEDXhgP1F5J1Bwl4JBZSn
image.png
oauth_personal_access表
image.png
管理私人访问令牌
user = App\User::find(1);
// Creating a token without scopes...
$token = $user->createToken('Token Name')->accessToken;
// Creating a token with scopes...执行这个报错,说第二个无效
$token = $user->createToken('My Token', ['place-orders'])->accessToken;
执行这个报错,说第二个无效
image.png
解决方法是,需要先定义,然后才能创建它,在AuthServiceProvider的boot定义
Passport::tokensCan([
'place-orders' => 'Place orders',
'check-status' => 'Check order status',
]);
路由保护
Route::get('/user1', function () {
//
echo 'come in';
})->middleware('auth:api');
比如我现在要访问user1的链接,将刚才生成的$token保存下来
我们使用postman测试
image.png
请求头
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer '.$accessToken,
],
令牌作用域
作用域(Scope)允许 API 客户端在请求账户授权的时候请求特定的权限集合.
例如,如果你在构建一个电子商务应用,不是所有的 API 消费者都需要下订单的能力,取而代之地,你可以让这些消费者只请求访问订单物流状态的权限,换句话说,作用域允许你的应用用户限制第三方应用自身可以执行的操作.
比如:淘宝卖家的营销工具,授权部分功能给工具使用调用和分析
AuthServiceProvider 的 boot 方法中使用 Passport::tokensCan 方法定义 API 的作用域
public function boot()
{
$this->registerPolicies();
Passport::routes();
//Passport::enableImplicitGrant();
Passport::tokensCan([
'place-orders' => 'Place orders',
'check-status' => 'Check order status',
]);
//
}
分配作用域到令牌
授权码
Route::get('/redirect', function () {
$query = http_build_query([
'client_id' => 'client-id',
'redirect_uri' => 'http://example.com/callback',
'response_type' => 'code',
'scope' => 'place-orders check-status',
]);
return redirect('http://your-app.com/oauth/authorize?'.$query);
});
颁发私人访问令牌
$token = $user->createToken('My Token', ['place-orders'])->accessToken;
检查作用域
Passport 提供了两个可用于验证输入请求是否经过已发放作用域的令牌认证的中间件。开始使用之前,添加如下中间件到 app/Http/Kernel.php 文件的 $routeMiddleware 属性:
'scopes' => \Laravel\Passport\Http\Middleware\CheckScopes::class,
'scope' => \Laravel\Passport\Http\Middleware\CheckForAnyScope::class,
全部包含返回使用scopes
Route::get('/orders', function () {
// Access token has both "check-status" and "place-orders" scopes...
})->middleware('scopes:check-status,place-orders');
任意一个scope
例子
路由
Route::get('/user/create_token', function(Request $request) {
$user = App\User::find(1);
$token = $user->createToken('My Token', ['place-orders'])->accessToken;
echo $token;
});
Route::get('/user/order', function () {
echo 'come in order';
})->middleware('auth:api','scope:check-status,place-orders');
这里中间件必须增加'auth:api',因为要认证之后才可以操作嘛,不然会提示说没有认证
image.png
加完之后
image.png
检查令牌实例上的作用域
当一个访问令牌认证过的请求进入应用后,你仍然可以使用经过认证的 User 实例上的 tokenCan 方法来检查这个令牌是否拥有给定作用域:
Route::get('/user/order2', function (\Illuminate\Http\Request $request) {
if ($request->user()->tokenCan('place-orders')) {
echo '我有权限';
}
})->middleware('auth:api');
image.png
使用 JavaScript 消费 API
我其实看不懂干嘛的,好像是说自动写入cookie里面
事件
颁发访问令牌和刷新令牌时触发事件
EventServiceProvider.php
protected $listen = [
'Laravel\Passport\Events\AccessTokenCreated' => [
'App\Listeners\RevokeOldTokens',
],
'Laravel\Passport\Events\RefreshTokenCreated' => [
'App\Listeners\PruneOldTokens',
],
];