Laravel Passport 結合 Dingo 實現 API 授權登入登出

leekachung發表於2019-12-24

準備工作

  • 引入Passport

  • 引入Guzzle

  • 引入Dingo

    composer require laravel/passport
    composer require guzzlehttp/guzzle
    composer require dingo/api
  • 遷移相應的migration檔案

    php artisan migrate
  • 安裝 Passport

    php artisan passport:install

此處執行結果 初次使用生成的Client ID為1和2

稍後使用的是後者的Client ID和Client Secret

可在專案使用的資料庫中oauth_clients資料表檢視到對應的id列,secret列

圖片


  • 編輯App\User.php 引用HasApiTokens

    可使用Passport提供的輔助方法 用來驗證身份和作用域
<?php
namespace App;

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

class User extends Authenticatable
{
    use HasApiTokens, Notifiable;
    // ...
}
  • 註冊Passport路由
    編輯App\Providers\AuthServiceProvider.php
<?php
namespace App\Providers;

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

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();
    }
}
  • 更新auth:api驅動

    編輯config/auth.php
    'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
    'api' => [
        'driver' => 'passport', // 這裡修改為passport
        'provider' => 'users',
    ],
    ],

實現

  • 使用者狀態控制器App\Http\Controllers\StatusController.php
<?php
namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Http\Requests\LoginRequest;
use Illuminate\Support\Facades\Auth;

use Exception;
use App\Traits\ResponseTrait;
use GuzzleHttp\Client as Guzzle;

class StatusController extends Controller
{
    use ResponseTrait; // 自定義的介面返回Trait 下面貼程式碼

    private $http;

    public function __construct()
    {
        // 不驗證tls
        $this->http = new Guzzle(['verify' => false]); 
    }

    public function login(LoginRequest $request)
    {
        try{
            // .env檔案配置APP_URL
            $response = $this->http->post(env('APP_URL').'/oauth/token', [
                'form_params' => [
                    // 使用密碼模式
                    'grant_type' => 'password', 
                    'client_id' => '填入你生成的Client ID',
                    'client_secret' => '填入你生成的Secret',
                    'username' => $request->username,
                    'password' => $request->password,
                    'scope' => '*',
                ],
            ]);
        }catch(Exception $e){
            $this->response(1, '登入失敗');
        }
        $this->response(0, '登入成功', ['__token' => json_decode((string) $response->getBody(), true)]);
    }

    public function logout()
    {
        if (Auth::check()) {
            Auth::user()->token()->delete();
        }
        $this->response(0, '退出成功');
    }
}
  • App\Http\Requests\LoginRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class LoginRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'username' => 'required|min:2|max:16',
            'password' => 'required|min:6|max:32'
        ];
    }
}
  • 路由檔案 routes/api.php
<?php
$api = app('Dingo\Api\Routing\Router');

$api->version('v1', function ($api) {
    # 登入
    $api->post('login', 'App\Http\Controllers\People\StatusController@login');

    $api->group(['middleware' => ['auth:api'], function ($api) {
        # 退出登入
        $api->get('logout', 'App\Http\Controllers\People\StatusController@logout');
    });
});
  • 介面統一返回Trait
<?php

namespace App\Traits;

trait ResponseTrait
{
    public function response($code, $desc=null, $result=null){
        $arr = [
            'code' => $code,
            'desc' => $desc,
            'result' => $result
        ];
        print json_encode($arr, true);
        exit(0);
    }
}

Postman測試

  • 登入
    登入測試

  • 登出
    登出測試

最後

如果想驗證的是別的欄位或其他規則

Passport提供了兩個方法findForPassportvalidateForPassportPasswordGrant

App\User.php新增




第一次在learnku寫作? 體驗很不錯

排版可能不是特別嚴謹

望多多包涵

By LiKachung

相關文章