Laravel study notes (28) laravel6 Authentication and Authorization (OAuth 2.0 code mode example)

  1. Access Token

Access Token There are two types, namely Bearer type and MAC type

  1. Configuring authorization server

Alternatively native file entry Request BaseRequest // such as request and response format are json

class BaseRequest extends Request
{
    public function expectsJson()
    {
        return true;
    }

    public function wantsJson()
    {
        return true;
    }
}
composer require laravel/passport

// 生成加密 access_token 的 key、密码授权客户端、个人访问客户端,其中password grant client是这次要用的
php artisan passport:install

Laravel \ Passport \ HasApiTokens Trait added to the App \ User model // provide some auxiliary function checks the authenticated user's token and use of

use HasApiTokens, Notifiable;
// 用于表单伪造
composer require guzzlehttp/guzzle
// config/auth.php

'defaults' => [
    'guard' => 'api',
    'passwords' => 'users',
],

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

    'api' => [
        'driver' => 'passport',
        'provider' => 'users',
        'hash' => false,
    ],
],
Passport::tokensExpireIn(now()->addDays(15)); // access_token 过期时间
Passport::refreshTokensExpireIn(now()->addDays(60)); // refresh_token 过期时间
// routes/api.php
Route::post('/oauth/token', '\Laravel\Passport\Http\Controllers\AccessTokenController@issueToken');

Route::post('/register', 'PassportController@register');
Route::post('/login', 'PassportController@login');
Route::post('/refresh', 'PassportController@refresh');
Route::post('/logout', 'PassportController@logout');

Route::get('test', function () {
    return 'ok';
})->middleware('auth');
<?php
namespace App\Http\Controllers;

use App\User;
use GuzzleHttp\Client;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;

class PassportController extends Controller
{
    protected $clientId;
    protected $clientSecret;

    public function __construct()
    {
        $this->middleware('auth')->except('login', 'register', 'refresh');
        // 从password grant client取值
        $client = \Cache::remember('password_client', 60 * 5, function () {
            return \DB::table('oauth_clients')->where('id', 3)->first();
        });
        $this->clientId = $client->id;
        $this->clientSecret = $client->secret;
    }

    protected function username()
    {
        return 'email';
    }

    public function register()
    {
        $this->validator(request()->all())->validate();

        $this->create(request()->all());

        return $this->getToken();
    }

    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => ['required', 'string', 'max:255', 'unique:users',],
            'email' => ['required', 'string', 'email', 'max:255',],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
        ]);
    }

    protected function create(array $data)
    {
        return User::forceCreate([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => password_hash($data['password'], PASSWORD_DEFAULT),
        ]);
    }

//    public function logout(Request $request)
//    {
//        auth()->user()->token()->revoke(); // 只会使 access_token 失效
//
//        return ['message' => '退出登录成功'];
//    }


    public function logout()
    {
        $tokenModel = auth()->user()->token();
        $tokenModel->update([
            'revoked' => 1,
        ]);

        \DB::table('oauth_refresh_tokens')
            ->where(['access_token_id' => $tokenModel->id])->update([
                'revoked' => 1,
            ]);

        return ['message' => '退出登录成功'];
    }

    public function login()
    {
        $user = User::where($this->username(), request($this->username()))
            ->firstOrFail();

        if (!password_verify(request('password'), $user->password)) {
            return response()->json(['error' => '抱歉,账号名或者密码错误!'],
                403);
        }

        return $this->getToken();
    }

    public function refresh()
    {
        $response = (new Client())->post('http://mushishi.com/api/oauth/token', [
            'form_params' => [
                'grant_type' => 'refresh_token',
                'refresh_token' => request('refresh_token'),
                'client_id' => $this->clientId,
                'client_secret' => $this->clientSecret,
                'scope' => '*',
            ],
        ]);

        return $response->getBody();
    }

    /**
     * @param Request $request
     * @param Client  $guzzle
     *
     * @return \Psr\Http\Message\ResponseInterface
     */
    private function getToken()
    {
        $response = (new Client())->post('http://mushishi.com/api/oauth/token', [
            'form_params' => [
                'grant_type' => 'password',
                'username' => request('email'),
                'password' => request('password'),
                'client_id' => $this->clientId,
                'client_secret' => $this->clientSecret,
                'scope' => '*',
            ],
        ]);

        return $response->getBody();
    }
}

Since the returned access_token is Bearer type, so when using the postman, when testing the test method, the test method is such that

Further, refresh_token refresh parameter passing method in FIG.
Here Insert Picture Description

  1. Access scope scope

Register scope

// AppServiceProvider的register()中 注册 scope
Passport::tokensCan([
	// 范围名称和描述
    'test1' => 'for test1',
    'test2' => 'for test2',
]);

Registration Middleware

// app/Http/Kernel.php的$routeMiddleware中注册中间件
'scopes' => \Laravel\Passport\Http\Middleware\CheckScopes::class,  // and
'scope' => \Laravel\Passport\Http\Middleware\CheckForAnyScope::class,  // or

Here Insert Picture Description
When 'scope' => 'test1'the time,

Route::get('test', function () {
    return 'ok';
})->middleware('scope:test1');	// 其访问范围是test1,可以访问

When 'scope' => 'test1'the time,

Route::get('test', function () {
    return 'ok';
})->middleware('scope:test2');	// 其访问范围是test2,不可以访问

[Scopes: test1, test2 test1] represents the range and test2 // and
[scope: test1, test2] represents the range test1 or test2 // or

When 'scope' => 'test1'the time,

Route::get('test', function () {
    return 'ok';
})->middleware('scopes:test1,test2');	// 其访问范围是test1 and test2,不可以访问

When 'scope' => 'test1'the time,

Route::get('test', function () {
    return 'ok';
})->middleware('scope:test1,test2');	// 其访问范围是test1 or test2,可以访问

Part of the correlation function scope

// 以注册的Scope
Laravel\Passport\Passport::scopeIds(); // ["test1","test2"]

// 以注册的所有Scope以及其描述
Laravel\Passport\Passport::scopes(); // [{"id":"test1","description":"for test1"},{"id":"test2","description":"for test2"}]

// 返回特定的已注册的Scope以及其描述
Laravel\Passport\Passport::scopesFor(['test1', 'check-status']); // [{"id":"test1","description":"for test1"}]

// 判断范围是否存在
Laravel\Passport\Passport::hasScope('place-orders'); // false
Published 40 original articles · won praise 0 · Views 762

Guess you like

Origin blog.csdn.net/qj4865/article/details/104363162