Laravel Passport认证-多用户多字段解决方案

孙才捷
2023-12-01

1. 安装

1-1. 进入项目文件夹,引入Laravel Passport

composer require laravel/passport=~4.0

1-2. 运行passport数据库迁移

php artisan migrate

1-3. 运行 passport:install 命令来创建生成安全访问令牌时所需的加密密钥,同时,这条命令也会创建用于生成访问令牌的「个人访问」客户端和「密码授权」客户端

php artisan passport:install

 1–4. 将 Laravel\Passport\HasApiTokens Trait 添加到 需要使用认证的(以App\User为例) 模型中,这个 Trait 会给你的模型提供一些辅助函数,用于检查已认证用户的令牌和使用范围:

<?php

namespace App;

use Laravel\Passport\HasApiTokens;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use HasApiTokens, Notifiable;

...

1–5. 在 AuthServiceProvider 的 boot 方法中调用 Passport::routes 函数。这个函数会注册发出访问令牌并撤销访问令牌、客户端和个人访问令牌所必需的路由:

<?php

namespace App\Providers;

use Laravel\Passport\Passport;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * 应用程序的策略映射。
     *
     * @var array
     */
    protected $policies = [
        'App\Model' => 'App\Policies\ModelPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        Passport::routes();
    }
}

1–6. 将配置文件 config/auth.php 中授权看守器 guards 的 api 的 driver 选项改为 passport。此调整会让你的应用程序在在验证传入的 API 的请求时使用 Passport 的 TokenGuard 来处理:

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'passport',
        'provider' => 'users',
    ],
],

1-7. 测试获取token(使用自己的测试域名,client_id及client_secret填写自己创建的密码授权客户端)

$http = new GuzzleHttp\Client;

$response = $http->post('http://your-app.com/oauth/token', [
    'form_params' => [
        'grant_type' => 'password',
        'client_id' => 'client-id',
        'client_secret' => 'client-secret',
        'username' => 'taylor@laravel.com',
        'password' => 'my-password',
        'scope' => '',
    ],
]);

return json_decode((string) $response->getBody(), true);

1-8. 如果以上的每一步操作都没错的话,会得到类似如下结果:

{
    "token_type": "Bearer",
    "expires_in": 31535999,
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjUzYzM5ZjJlN2YxMzI5N2Q5Y2FlZjFkYzVhZDA3NjQxYzU0YWY3OWIyYzFmMGMwYjM5OTFhZjZmNjk3YjdlNGQwZWQxYTYyOGE4MjkzOWRiIn0.eyJhdWQiOiI2IiwianRpIjoiNTNjMzlmMmU3ZjEzMjk3ZDljYWVmMWRjNWFkMDc2NDFjNTRhZjc5YjJjMWYwYzBiMzk5MWFmNmY2OTdiN2U0ZDBlZDFhNjI4YTgyOTM5ZGIiLCJpYXQiOjE1Mjc3Mzc3MDQsIm5iZiI6MTUyNzczNzcwNCwiZXhwIjoxNTU5MjczNzA0LCJzdWIiOiIxIiwic2NvcGVzIjpbInRlc3QiXX0.eTc7-MoB2_5PfKuh6hlN0Vi3-sjLqZ9-N1-YGPvCTjs1oE_P0gmLfI-dsWDDrY9AC5O1jhdshlmB0odnC5Az3GEctAdnqzuVubn5Iq6nHcH4AgD7YJFzAIMXf4KlsyaO3cA7Ohz1Utnv0eHVYA-x01tK9KT0P-Yp63SsZzgtGsXSQgoqOYsy8QmfE4pr54zihBfwvn4s8A_XBO2EXJmYa1r3k3SyQY8dhvxzAg_Ze9CvAtp-v_zwXx6e1PTEdVJyXKXxrIS-7eXtVX01PLvkHZVRbv_HkP3ouJE_a1jzIL_JztpNMtkUOuelV7bz20mzVkVFyP_P4XW8Fm9uIVuivT_OQet1OyhlKv3ORuXVF6sD2fuYEv-Lcc3OVNtxy_80Nl2m4pZCowyf17QnbZhuWbgjmQJrcKfHHhq-yFohb7FGR8meHxgvB-InfU23PINupitFA_G0seuk9lvvXAFArqvkuAyOTP0wBzNHTl4HT4qkM2c2KeZGl8FQ4Jd_hkDMBuAmiNQ8XE7LS1kkwDOaS8hKuMkTps4fNb7gfWaIFa4FfBRm-ZWanVxU61zooxOmajfDPyAYG3_SVkfObSlMGopAiKM6Aly7o78xJGLdCl0Z2aCws3z1k_VZpdv9bmwGzWJpysldcTwyBLyoDfAQP8y7Plxe09bmfus-JkDrWGU",
    "refresh_token": "def502003c32f3cdcb5fc33a27235d9effc81318233071fa0be74c69d0ec8bb4e649183d34eb993cd36a6c93c45ea91e47ce835dad785ac595723cbcbd069a86338e80289fc16d8732f26da9db915e7f8fd8f7da5983e426e8180c908ef2e85c7c313c94ebc8f90830362a1fae39bd0c7fa95efd989c85751cabbe5270c8f608ca7f446c51a8c39a6c9ff5600cef8a7417f8c9a3b34b3c25ff7c46160b7e4530f067f0365b451fb0dec42adc40cae3336b7e4028bd8df48f12f5de0444963ab05099dd15394f24d0986f894ea66e7755f7e29c92c18fe70ab0134673a8dae8ecaa6d05becf529ff281359b487eedef0686646057e84971eb83347c90b7f402010ae662aec7482c750627bac790971db12382e3d55851a454407db608d23707eb23a50bdfab5e8e273a0e67d446ed667c4a12fddc5082a1557eb3bef2353f8a152e5804ab919772529e2f455fb8a1821b53726d6b7b24aaf2d14f72648f3d698810f24557c3"
}

 

2. 多用户登录

2–1. 引入multiauth扩展包

composer require smartins/passport-multiauth

2–2. 以企业和机构为例, 创建数据模型并覆盖findForPassport方法(用于修改默认验证字段)。未使用常见的username字段。如企业用户名字段tel

<?php

namespace App\Models;

use Laravel\Passport\HasApiTokens;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class Company extends Authenticatable
{
    use HasApiTokens, Notifiable;

    /**
     * 修改认证时的默认username字段为tel
     */
    public function findForPassport($username) {
        return $this->where('tel', $username)->first();
    }
}

2–3. 配置文件 config/auth.php 中 providers 数组增加对应的模型

'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],

'companys' => [
            'driver' => 'eloquent',
            'model' => App\Models\Company::class,
        ],

],

2–3. 在文件 app/Http/Kernelmiddlewares的$middlewareGroups中,注册自定义的PassportCustomProvider和PassportCustomProviderAccessToken

class Kernel extends HttpKernel
{
    ...

    /**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            'throttle:60,1',
            'bindings',
            'custom-provider',
        ],

        'custom-provider' => [
            \SMartins\PassportMultiauth\Http\Middleware\AddCustomProvider::class,
            \SMartins\PassportMultiauth\Http\Middleware\ConfigAccessTokenCustomProvider::class,
        ]
    ];

    ...
}

2–4. 在 AuthServiceProvider 增加 access token 对应的 passport routes

use Route;
use Laravel\Passport\Passport;

class AuthServiceProvider extends ServiceProvider
{
    ...

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        Passport::routes();

        Route::group(['middleware' => 'api'], function () {
            Passport::routes(function ($router) {
                return $router->forAccessTokens();
            });
        });
    }
    ...
}

2–5. 测试Company的登录,在参数里面增加provider=companys(对应2-3中添加的provider),注:帐号和密码以自己实际为准

$http = new GuzzleHttp\Client;

$response = $http->post('http://your-app.com/oauth/token', [
    'form_params' => [
        'grant_type' => 'password',
        'client_id' => 'client-id',
        'client_secret' => 'client-secret',
        'username' => 'username',
        'password' => 'password',
        'scope' => '',
        'provider' => 'companys'
    ],
]);

return json_decode((string) $response->getBody(), true);

2-6. 如果以上的每一步操作都没错的话,会得到类似如下结果:

{
    "token_type": "Bearer",
    "expires_in": 31535999,
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjUzYzM5ZjJlN2YxMzI5N2Q5Y2FlZjFkYzVhZDA3NjQxYzU0YWY3OWIyYzFmMGMwYjM5OTFhZjZmNjk3YjdlNGQwZWQxYTYyOGE4MjkzOWRiIn0.eyJhdWQiOiI2IiwianRpIjoiNTNjMzlmMmU3ZjEzMjk3ZDljYWVmMWRjNWFkMDc2NDFjNTRhZjc5YjJjMWYwYzBiMzk5MWFmNmY2OTdiN2U0ZDBlZDFhNjI4YTgyOTM5ZGIiLCJpYXQiOjE1Mjc3Mzc3MDQsIm5iZiI6MTUyNzczNzcwNCwiZXhwIjoxNTU5MjczNzA0LCJzdWIiOiIxIiwic2NvcGVzIjpbInRlc3QiXX0.eTc7-MoB2_5PfKuh6hlN0Vi3-sjLqZ9-N1-YGPvCTjs1oE_P0gmLfI-dsWDDrY9AC5O1jhdshlmB0odnC5Az3GEctAdnqzuVubn5Iq6nHcH4AgD7YJFzAIMXf4KlsyaO3cA7Ohz1Utnv0eHVYA-x01tK9KT0P-Yp63SsZzgtGsXSQgoqOYsy8QmfE4pr54zihBfwvn4s8A_XBO2EXJmYa1r3k3SyQY8dhvxzAg_Ze9CvAtp-v_zwXx6e1PTEdVJyXKXxrIS-7eXtVX01PLvkHZVRbv_HkP3ouJE_a1jzIL_JztpNMtkUOuelV7bz20mzVkVFyP_P4XW8Fm9uIVuivT_OQet1OyhlKv3ORuXVF6sD2fuYEv-Lcc3OVNtxy_80Nl2m4pZCowyf17QnbZhuWbgjmQJrcKfHHhq-yFohb7FGR8meHxgvB-InfU23PINupitFA_G0seuk9lvvXAFArqvkuAyOTP0wBzNHTl4HT4qkM2c2KeZGl8FQ4Jd_hkDMBuAmiNQ8XE7LS1kkwDOaS8hKuMkTps4fNb7gfWaIFa4FfBRm-ZWanVxU61zooxOmajfDPyAYG3_SVkfObSlMGopAiKM6Aly7o78xJGLdCl0Z2aCws3z1k_VZpdv9bmwGzWJpysldcTwyBLyoDfAQP8y7Plxe09bmfus-JkDrWGU",
    "refresh_token": "def502003c32f3cdcb5fc33a27235d9effc81318233071fa0be74c69d0ec8bb4e649183d34eb993cd36a6c93c45ea91e47ce835dad785ac595723cbcbd069a86338e80289fc16d8732f26da9db915e7f8fd8f7da5983e426e8180c908ef2e85c7c313c94ebc8f90830362a1fae39bd0c7fa95efd989c85751cabbe5270c8f608ca7f446c51a8c39a6c9ff5600cef8a7417f8c9a3b34b3c25ff7c46160b7e4530f067f0365b451fb0dec42adc40cae3336b7e4028bd8df48f12f5de0444963ab05099dd15394f24d0986f894ea66e7755f7e29c92c18fe70ab0134673a8dae8ecaa6d05becf529ff281359b487eedef0686646057e84971eb83347c90b7f402010ae662aec7482c750627bac790971db12382e3d55851a454407db608d23707eb23a50bdfab5e8e273a0e67d446ed667c4a12fddc5082a1557eb3bef2353f8a152e5804ab919772529e2f455fb8a1821b53726d6b7b24aaf2d14f72648f3d698810f24557c3"
}

3. 多字段登录

待完善。。。

4. 使用token

当调用 Passport 保护下的路由时,接入的 API 应用需要将访问令牌作为 Bearer 令牌放在请求头 Authorization 中,如下:

$response = $client->request('GET', '/api/user', [
    'headers' => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer '.$accessToken,
    ],
]);

 

转载于:https://my.oschina.net/happykevin/blog/1821919

 类似资料: