單點登入說明
單點登入(Single Sign On),簡稱為 SSO,意思是在多個應用系統中,使用者只需要登入一次就可以訪問所有相互信任的其它應用系統。一般常用於同一家公司的不同子系統之間的登入認證。
需要外掛
// passport
composer require laravel/passport
// predis
composer require predis/predis
首先我們建立三個專案
composer create-project --prefer-dist laravel/laravel login.sso.test
composer create-project --prefer-dist laravel/laravel home.sso.test
composer create-project --prefer-dist laravel/laravel my.sso.test
env 配置
APP_KEY=***
DB_CONNECTION=mysql
DB_HOST=192.168.10.10
DB_PORT=3306
DB_DATABASE=sso
DB_USERNAME=homestead
DB_PASSWORD=secret
BROADCAST_DRIVER=log
CACHE_DRIVER=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis
SESSION_LIFETIME=120
SESSION_DOMAIN=.sso.test
SESSION_DOMAIN
我們在這個 env 新增了這個配置 是為了設定config/session.php
中配置項 domail
設定 Cookie
域名
三個專案的 APP_KEY
需要設定為一樣否者不行
登入認證中心
安裝擴充套件包
composer require laravel/passport
composer require predis/predis
執行資料庫遷移
php artisan migrate
執行 artisan
命令
php artisan passport:install
安裝laravel 自帶 認證中心
composer require laravel/ui
npm install && npm run dev
// 會提示建立頁面 不需要的頁面可以不建立
composer require laravel/ui
config/auth.php
配置
guards = [
...
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
]
配置中介軟體
protected $middlewareGroups = [
'wbe' => [
...
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],
'api' => [
...
'throttle:60,1',
'bindings',
]
],
配置路由routes/api.php
// 為了方便測試 取消 token驗證
Laravel\Passport\Passport::$ignoreCsrfToken = true;
Route::middleware('auth:api')->group(function () {
Route::get('/user/{id}', function ($id) {
return \App\User::find($id);
});
});
登入認證 中心專案完成
home.sso.test
專案
安裝擴充套件包
composer require laravel/passport
composer require predis/predis
安裝laravel
自帶認證中心
composer require laravel/ui
npm install && npm run dev
// 會提示建立頁面 不需要的頁面可以不建立
// 子系統不需要登入註冊找回密碼等頁面 所以 全部選擇 no
composer require laravel/ui
自定義 Provider
我們需要自定一個 SsoUserProvider 來實現從主系統獲取使用者資訊,在 app
目錄下建立一個 Extensions
目錄 建立SsoUserProvider
// 建立資料夾
mkdir Extensions
// 進入目錄
cd Extensions
// 建立檔案
touch SsoUserProvider.php
SsoUserProvider.php
程式碼
<?php
namespace App\Exceptions;
use GuzzleHttp\Client;
use GuzzleHttp\Cookie\CookieJar;
use Illuminate\Auth\EloquentUserProvider;
class SsoUserProvider extends EloquentUserProvider
{
public function retrieveById($identifier)
{
$http = new Client();
$cookies = CookieJar::fromArray(
[
'laravel_token' => $_COOKIE['laravel_token'],
],
'.sso.test'
);
$response = $http->request(
'GET',
'http://login.sso.test/api/user/'.$identifier,
[
'cookies' => $cookies,
]
);
$user = json_decode($response->getBody()->getContents(), true);
$model = $this->createModel();
$model->forceFill($user);
return $model;
}
}
以上域名 可以走 自定義配置檔案
這個自定義類中,我們同過API
介面獲取使用者資訊並返回
然後設定 config/auth.php
的 providers
配置項修改如下
'users' => [
'driver' => 'sso',
'model' => App\User::class,
],
最後我們在 AuthServiceProvider .php
的 boot
方法註冊自定義的 UserProvider
類讓它生效
use Illuminate\Support\Facades\Auth;
use App\Exceptions\SsoUserProvider;
public function boot()
{
...
Auth::provider(
'sso',
function ($app, $config) {
return new SsoUserProvider($app->make('hash'), $config['model']);
}
);
}
然後們修改 app/Http/Controllers/Auth/LoginController.php
將登入重定向到登入系統
public function showLoginForm()
{
return redirect('http://login.sso.test/login');
}
註冊 找回密碼 同理
退出登入
我們修改 app/Http/Controllers/Auth/LoginController.php
檔案
public function logout(Request $request)
{
$http = new Client();
$cookies = CookieJar::fromArray(
[
// 注意是 laravel_session 不是laravel_token
'laravel_session' => $_COOKIE['laravel_session'],
'XSRF-TOKEN' => $_COOKIE['XSRF-TOKEN'],
],
'.sso.test'
);
$response = $http->request('POST', 'http://login.sso.test/logout', ['cookies' => $cookies]);
if ($response->getStatusCode() == 200) {
$request->session()->invalidate();
return $this->loggedOut($request) ?: redirect('/');
}
abort(500);
}
登入認證中心 主專案
因為 post 提交需要 _token
這裡為了方便 直接在 app/Http/Middleware/VerifyCsrfToken.php
中的 $except
新增退出路由 否者會 419 錯誤
protected $except = [
'/logout'
];
my.sso.test 同上 即可
歡迎評論 給出意見 及修改
本作品採用《CC 協議》,轉載必須註明作者和本文連結