Laravel 通过 cookie 实现基于 session 的单点登录 
                                                    
                        
                    
                    
  
                    
                    单点登录说明
单点登录(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.testenv 配置
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.testSESSION_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/uiconfig/auth.php 配置
guards = [
        ...
         'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'api' => [
            'driver' => 'passport',
            'provider' => 'users',
        ],
]配置中间件
protected  $middlewareGroups = [
   'web' => [
        ...
        \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.phpSsoUserProvider.php  代码
<?php
namespace App\Exceptions;
use GuzzleHttp\Client;
use GuzzleHttp\Cookie\CookieJar;
use Illuminate\Auth\EloquentUserProvider;
class SsoUserProvider extends EloquentUserProvider
{
    public function retrieveById($identifier)
    {
        /**
        * 确保百分之百有 laravel_token 如果没有继续去登录
        */
        if (isset($_COOKIE['laravel_token']) && $_COOKIE['laravel_token']) {
            $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;
        } else {
            return redirect('http://login.sso.test/login');
        }
}以上域名 可以走 自定义配置文件
这个自定义类中,我们同过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 协议》,转载必须注明作者和本文链接
 
           自由与温暖是遥不可及的梦想 的个人博客
 自由与温暖是遥不可及的梦想 的个人博客
         
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
                     
                     
             
             
             
             
             
             
             
             
           
           关于 LearnKu
                关于 LearnKu
               
                     
                     
                     粤公网安备 44030502004330号
 粤公网安备 44030502004330号 
 
推荐文章: