安裝
composer require laravel/passport=~4.0
notes:
1)確保系統安裝unzip蔽午、zip等命令。
2)composer 安裝出現 Authentication required (packagist.phpcomposer.com) 問題酬蹋,修改composer.json 中的源及老,repositories.packagist.url = https://packagist.laravel-china.org 。
注冊服務提供者
在config/app.php的providers 數組中加入 Laravel\Passport\PassportServiceProvider::class
遷移數據庫
php artisan migrate //生成用于存儲客戶端和令牌的數據表
生成加密健
php artisan passport:install
1范抓、生成oauth-private.key(用于構建認證服務器)骄恶,oauth-public.key(用于構建資源服務器)
2、oauth_clients數據庫生成「個人訪問」客戶端和「密碼授權]兩條數據匕垫。
配置Passport(參考官方文檔)
在Model中僧鲁,我們需要增加 HasApiTokens class
在AuthServiceProvider中, 增加 "Passport::routes()"
在 auth.php中, 更改 api 認證方式為passport
申請客戶端以及私人訪問令牌 (兩種方式)
1. 命令形式(不方便客戶注冊)
php artisan passport:client
2. Passport Vue 組件
php artisan vendor:publish --tag=passport-components //發(fā)布 Passport Vue寞秃,組件位于resources/assets/js/components下
//注冊到resources/assets/js/app.js 文件斟叼,記得要放在new Vue上面
Vue.component(
'passport-clients',
require('./components/passport/Clients.vue')
);
Vue.component(
'passport-authorized-clients',
require('./components/passport/AuthorizedClients.vue')
);
Vue.component(
'passport-personal-access-tokens',
require('./components/passport/PersonalAccessTokens.vue')
);
//編譯前端資源
npm install //此處報錯,移步larravel Mix文檔
npm run dev
編譯后資源放在public/js/app.js下
//組件放入應用模板(記得引入編譯后的app.js)
<passport-clients></passport-clients>
<passport-authorized-clients></passport-authorized-clients>
<passport-personal-access-tokens></passport-personal-access-tokens>
以上認證服務器都已經搭建完成
第三方應用實現登錄
1. 申請客戶端
回調地址 http://third.plat.goods/dew/sso
申請授權碼和訪問令牌
//獲取授權碼 code (第一次交互)
$query = http_build_query(array(
'client_id' => 3,
'redirect_uri' => 'http://third.plat.goods/dew/sso', //地址必須為上面的回調地址
'response_type' => 'code', //固定值
'scope' => '',
'state' => urlencode('http://laravel.plat.goods/user') //可以放用戶訪問的地址春寿。
));
return redirect('http://laravel.plat.goods/oauth/authorize?'.$query); ///laravel.plat.goods為上面認證服務器
//獲取訪問令牌 access token 以及向資源服務器請求用戶信息
授權后會重定向回調地址
Route::get('/dew/sso', 'SSOController@callback'); //路由文件里添加
php artisan make:controller SSOController //創(chuàng)建文件
<?php
namespace App\Http\Controllers;
use App\Models\User;
use GuzzleHttp\Client;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class SSOController extends Controller
{
protected $http;
public function __construct()
{
$this->http = new Client();
}
/**
* 獲取授權碼后的回調URL
* @param Request $request
* @return \Illuminate\Http\RedirectResponse
*/
public function callback(Request $request)
{
$token = $this->token($request); //第二次交互
$login = $this->login($token);//第三次交互
if($login){
if($request_url = $request->input('state', null)){
$request->session()->put('url.intended', urldecode($request_url));
}
return redirect()->intended(); //跳轉到 http://laravel.plat.goods/user
}else{
return redirect()->to('http://laravel.plat.com/home/public/login'); //服務提供商網站必須登錄
}
}
/**
* 獲取access token
* @param $request
* @return array|mixed
*/
protected function token($request)
{
$code = $request->code;
if($code) {
try {
$response = $this->http->post('http://laravel.plat.goods/oauth/token', [
'form_params' => [
'grant_type' => 'authorization_code', //固定值
'client_id' => 3,
'client_secret' => 'UihXNHoSqohdtQ8Js6Av7AOyk3GBNB9rJziDPaWf',
'redirect_uri' => 'http://third.plat.goods/dew/sso',
'code' => $code,
],
]);
$response_data = json_decode((string)$response->getBody(), true);
return $response_data;
} catch (\Exception $e) {
Log::error('get token by code failed: '.$code.' - '.$e->getMessage().' - '.$e->getTraceAsString());
return [];
}
}else{
return [];
}
}
/**
* 通過token獲取用戶信息犁柜,并進行登錄操作
* @param $token
* @return bool
*/
protected function login($token)
{
if(empty($token)) return false;
$access_token = $token['access_token'];
try {
// 資源服務器和認證服務器放在了一起,可以獨立堂淡。
$response = $this->http->request('GET', 'http://laravel.plat.goods/api/user', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => $token['token_type'] . ' ' . $access_token,
]
]);
$users_body = $response->getBody();
$data = json_decode($users_body, true);
if($data) {
$user = new User($data);
//because of employee_id is guarded
$user->setAttribute($user->getKeyName(), $data['employee_id']);
//login user in my system
auth()->login($user, false);
return true;
}else{
return false;
}
}catch (\Exception $e){
Log::error('get user failed by access_token:'.$access_token.'|'.$e->getMessage());
return false;
}
}
}
//設置資源文件
Route::middleware('auth:api')->get('/user', 'UserController@user'); //routes/api.php文件中設置
php artisan make:controller UserController //創(chuàng)建文件
class UserController extends Controller
{
public function user(Request $request)
{
return $request->user();
}
}