laiyuquan

博客

Oauth2--Laravel-Passport--API认证

OAuth2基础概念

Oauth2.0是什么?

OAuth:Open Authorization:OAuth协议为用户资源的授权提供一个安全、开放而又简单的标准。即第三方无需使用用户名和密码就能获取用户资源的授权(参考第三方登录流程)

Why 使用OAuth2?

任何身份认证,本质上都是基于请求方的不信任产生的。本质就是解决各平台应用的可信任问题;数据的安全性是互联网公司核心。数据泄露 轻则丢失用户,重则直接倒闭;(最近facebook的危机事件)

OAuth2基本流程

OAuth2成员:

1. Resource Owner(资源拥有者:用户)

2. Client (第三方接入平台:请求者 或称 客户端)

3. Authorization Server (认证服务器)

4. Resource Server (服务器资源:数据中心)

基本流程

《Oauth2--Laravel-Passport--API认证》

(A)用户打开客户端以后,客户端要求用户给予授权

(B)用户同意给予客户端授权。

(C)客户端使用上一步获得的授权,向认证服务器申请令牌。

(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。

(E)客户端使用令牌,向资源服务器申请获取资源。

(F)资源服务器确认令牌无误,同意向客户端开放资源。

OAuth2四种授权模式

  • 授权码模式(authorization code)
  • 简化模式(implicit)
  • 密码模式(resource owner password credentials)
  • 客户端模式(client credentials)

Laravel-Passport 实战

composer安装

composer require laravel/passport  ~4.0

数据迁移

php artisan migrate

创建令牌

php artisan passport:install

添加Laravel\Passport\HasApiTokens trait 到 App\User 模型

<?php

namespace App;

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

class User extends Authenticatable
{
    use Notifiable , HasApiTokens;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];
}

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
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        'App\Model' => 'App\Policies\ModelPolicy',
    ];

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

        Passport::routes();
    }
}

最后,在配置文件 config/auth.php 中,需要设置 api 认证 guard 的 driver 选项为**== **passport==

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

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

授权码模式

颁发客户端

php artisan passport:client

《Oauth2--Laravel-Passport--API认证》

请求认证

路由定义在 routes/api.php 中

Route::get('/redirect', function (){

    $query = http_build_query([
        'client_id' => '7',
        'redirect_uri' => 'http://test.app/auth/callback',
        'response_type' => 'code',
        'scope' => '',
    ]);

    return redirect('http://test.app/oauth/authorize?' . $query);
});

同时在 routes/web.php 注册 auth/callback 路由:

Route::get('/auth/callback', function (\Illuminate\Http\Request $request){

    $http = new GuzzleHttp\Client();

    $response = $http->post('http://test.app/oauth/token', [
        'form_params' => [
            'grant_type' => 'authorization_code',
            'client_id' => '7',  // your client id
            'client_secret' => '4UPfnoil8MTlB5DlZkOppyujNIwpDNqzJqrkF8MI',   // your client secret
            'redirect_uri' => 'http://test.app/auth/callback',
            'code' => $request->code,
        ],
    ]);


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

});

浏览器中访问 http://laravel55.dev/api/redirect

直接跳转到认证服务器的 登录页面 进行授权

《Oauth2--Laravel-Passport--API认证》

输入账号 密码后 跳转到授权确认页面:
《Oauth2--Laravel-Passport--API认证》

点击确认后:
《Oauth2--Laravel-Passport--API认证》

这样就拿到access_token,通过access_token去资源服务器拿出相应的资源信息

刷新令牌、创建client客户端、自定义视图 甚至 是控制器 这些就看需求了

密码授权模式

如果你是给自己的应用,那就没有必要走完整的授权码模式了,OAuth2提供了密码模式。(本质还是信任原因)

创建密码授权客户端

php artisan passport:client –password

请求令牌

Route::get('/auth/password', function (\Illuminate\Http\Request $request){

    $http = new \GuzzleHttp\Client();

    $response = $http->post('http://test.app/oauth/token', [
        'form_params' => [
            'grant_type' => 'password',
            'client_id' => '4',
            'client_secret' => 'LSimgXozmPk2sWg2RXkMKkfWvwx7XtV2jV61briX',
            'username' => 'laiyuquan1014@163.com',
            'password' => 'you password',
            'scope' => '*',
        ],
    ]);

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

最终也是直接得到access_token
《Oauth2--Laravel-Passport--API认证》

客户端模式

适用于机器对机器的授权认证


Route::get('/client',function(){

    $guzzle = new GuzzleHttp\Client;

    $response = $guzzle->post('http://test.app/oauth/token', [
        'form_params' => [
            'grant_type' => 'client_credentials',
            'client_id' => '7',
            'client_secret' => '4UPfnoil8MTlB5DlZkOppyujNIwpDNqzJqrkF8MI',
            'scope' => '*',
        ],
    ]);

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


});

最终返回

{
token_type: "Bearer",
expires_in: 31536000,
access_token: "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjM5NmJjMjhiNDIzNDhkNjFhYWQxOTVjMTkzM2QyY2YyN2VmYzI2YTk1M2I0ODQ4MDEyMWEwZDE1NDEwZThlYzg4ZjkwNDZhMmEzY2MxZTA1In0.eyJhdWQiOiI3IiwianRpIjoiMzk2YmMyOGI0MjM0OGQ2MWFhZDE5NWMxOTMzZDJjZjI3ZWZjMjZhOTUzYjQ4NDgwMTIxYTBkMTU0MTBlOGVjODhmOTA0NmEyYTNjYzFlMDUiLCJpYXQiOjE1MjQ1NTkwMzUsIm5iZiI6MTUyNDU1OTAzNSwiZXhwIjoxNTU2MDk1MDM1LCJzdWIiOiIiLCJzY29wZXMiOltdfQ.slOQnhgvN5h9znKWeDVYeg5xdsLK150dBHeU5vgXx3LNVCvDwRb-ze4gHHrWNINfsBVKpuMwA5gkESAQxoDfv862qcug4PrLcgAFXIPdkkc3Xi0wY6jD0mnLgTjcrta1W92zK-1CVn0o0pB6c1spQ33IvREdmDTUEOC8zJdsWdZNxhI9p1qYNCDq1gI0mG3OOzcXRC48YDBrPZ_U_dxCmoVbALhexCgTWEa8uto_1dMpmhq3B7Om7tKGITmDPjhJzKrcOH9GjSRUZduVkriY62B6Ll_ZcAvIKkLiI8y-RnxxoOf_9F75gcI1Jl_dEb1ERglwxU84t27Z3PsrVRflWX9Zv5SuI6FSI3rDYuQZEZzRSV6Nk6XjXfSj2HJW16TZHppvppoCJXlQpK1T4juzS6_QtdpEZuIfq6RiOBoEQnLqihtI9ICxGgqAoYeEeGeHxvnmYpvI3tSV6xUQb29sGTbjpyhM1EKpqusWxhmpvA_0liBFgGXvDCBwPgxJpu3_sNu8tqXyx60fWMsJ7mWHTKJl1jWx7Ri9JCEX4Xk-4_pIWpmgwSEADmpkrvhKRm1j1zNyYPzDnXUQq8q2vjxi2ZrbN40zEZ-uDmC63WL5Q9mmWysGoL-mgg1T2vwJ6jzW1l2gn_DMltwe8hfxE6v-y77KEpi4TuQKioBs3oRfMpI"
}

私人令牌

服务后台直接颁发access_token 给客户端,不需要走典型的授权码重定向流程;

创建私人访问客户端

php artisan passport:client –personal

创建access_token

$user = User::find(1);

$token = $user->createToken('Token Name')->accessToken;


直接返回access_token

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjE1MDYzMzdiYzg1ZTc5OTU0MmZiZmE5NWQ2MWIxNDQ4YTcyN2E3OTg2N2Y2ZWU1Y2Y4MGUwZjY4Y2M3OTMwNmVhMjNmYmFmYjA5ODU2ODNhIn0.eyJhdWQiOiIzIiwianRpIjoiMTUwNjMzN2JjODVlNzk5NTQyZmJmYTk1ZDYxYjE0NDhhNzI3YTc5ODY3ZjZlZTVjZjgwZTBmNjhjYzc5MzA2ZWEyM2ZiYWZiMDk4NTY4M2EiLCJpYXQiOjE1MjQ1Njk5NzUsIm5iZiI6MTUyNDU2OTk3NSwiZXhwIjoxNTU2MTA1OTc1LCJzdWIiOiIxIiwic2NvcGVzIjpbIm5hbWUiXX0.oCEdUlmLbXej9smO2KjXVq2myK_EHVOfi5Rj-poLPaU2R5pE331diezq5Jr96WVDzwC2dhLMEonDK7XUacUB93cKXGX6i0H4Wp0sCdDitORXHdHKRfmVzIEH7yXLwNaa8NoL-Bf5nKEjFftA1yyJOr-zwIghqs0YCK5JwHBzk-szgHIPxBDzTOfBCAHk0xUSsWyNXItRx6Cs-6hNJLn8oSYVgAw81LstZFH6xbvKHWP6zZDQ_nyV4GejSw0ztUZMF5Oi5wpYBZJjnaUyVVYLF64wMlse-CqRFUUKnTZzaYhs9_KfGN8qxm7xSpVtulm0DS1SjUfv_CR7JT1aZP44r3SImlDnZDf7AOxxAukRBR1ltN5012QK5m9GdltnG7g5za4JFmHQsJZHnk7dfPGyhdY3-kZMLm4i1c_U4p8TX5mQqc9tjVvL1OCdXF_jXpLY4sCVpChRrjX_VLFf_5CO-BMueBdtUtj06VQDzrvR7-GKoWsGoOYLqnG8VUItIj15DITXixd6yDp7WeRB5C3B0v8uR6r4-aflnM8as1NzYrwz5diO0IppyE0tbWac6V3Hl_t5slmegAju5aA03Rue11yxiEd81wYRRQQ3gbjWgFdtRHR26qvuEBk4JOUmAvQE8o1f7JgB8ih6YJSKPBCWOWtlC91rpBCJcISMN_w9NYY

具体使用access_token

参考文档如下:
《Oauth2--Laravel-Passport--API认证》


参考资料如下:

https://segmentfault.com/a/1190000010540911

http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html

https://blog.csdn.net/seccloud/article/details/8192707

https://laravel.com/docs/5.5/passport

OAuth2理解起来并不复杂, 但考虑的因素比较多,在真正实践的过程中 需要多考虑很多状况(比如:令牌刷新时间 、 令牌作用域…)

点赞

发表评论