Laravel study notes (27) laravel6 authentication and authorization (OAuth 2.0 authorization code pattern instance)

Reference website

  1. Prepare two servers, a third-party server simulation, a mock authorization server
  2. The authorization server (micro-channel)

Passport Composer installed by the package manager:
which laravel / passport provide OAuth authentication service

composer require laravel/passport

And the token is created to store the client data sheet:

php artisan migrate

Next, run the passport: install command to create an encryption key for generating the security access token, at the same time, this command will create a "personal visit" to generate an access token client (Personal Access Client) and "password authentication" The client (password Grant client):

php artisan passport:install

// 或者使用
php artisan passport:keys			// 加密生成的 access_token
php artisan passport:client			// 创建自定义客户端,生成client ID 和 client secret

PS: access_token generated position --storage / oauth-private.key

After the above command is executed, please Laravel \ Passport \ HasApiTokens Trait added to the App \ User model, this model provides Trait will give you some auxiliary functions for checking the authenticated user's token and use of:

use HasApiTokens, Notifiable;

Next, call the Passport :: routes registered token associated routing method in the boot of AuthServiceProvider

Passport::routes();

// Laravel中默认refresh_token 过期时间等于access_token 过期时间,
// refresh_token 过期时间要大于access_token 过期时间,因为只有这样,当access_token过期后,由于refresh_token 没过期,可以通过refresh_token 去刷新access_token
Passport::tokensExpireIn(now()->addDays(15)); // access_token 过期时间
Passport::refreshTokensExpireIn(now()->addDays(60)); // refresh_token 过期时间

Finally, the configuration file config / auth.php an authorized guard guards of the driver api option to passport. This adjustment will make your application in TokenGuard using the Passport when validating incoming request to process API:

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

    'api' => [
        'driver' => 'passport',
        'provider' => 'users',
    ],
],
  1. Third-party server (B station)

The first step, A website provides a link, it will jump to the B site after the user clicks, the user authorization data to the A-site uses. Here is a schematic Jump A site B links to site.

https://b.com/oauth/authorize?
  response_type=code&
  client_id=CLIENT_ID&
  redirect_uri=CALLBACK_URL&
  scope=read

Code:

(1) Routing

// 登录页面
Route::view('/login', 'login');

(2) Viewresources/views/login.blade.php

// 跳转到/mushishi/login,根据示意链接,发送链接
<a href="/mushishi/login">微信登陆</a>

(3) routing

On CSRF attack
http_build_query

$clientId = 1;	// 授权服务器生成的client_id,要与数据库一致
$clientSecret = 'T51YiRBezu2QZzmodyTGPKdNJZ4MpeiGPv5PmjiJ';	// 授权服务器生成的client_secret,要与数据库一致

Route::get('/lishen/login',
    function (\Illuminate\Http\Request $request) use ($clientId) {
    	// state用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击,可设置为简单的随机数加session进行校验
        $request->session()->put('state', $state = Str::random(40));

        $query = http_build_query([
            'client_id' => $clientId,	// 授权服务器生成的client_id,要与数据库一致
            'redirect_uri' => 'http://www.mushishi.com/auth/callback',	// 授权服务器生成的redirect,要与数据库一致
            'response_type' => 'code',	//固定
            'scope' => '*',	// 应用授权作用域
            'state' => session('state'),
        ]);

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

Note: here encountered a pit ! ! ! Redirection URL (redirect_uri) If the jump without the www, but http://mushishi.com/auth/callbackthe authorization server-side redirect to authorize and confirm the client laravel page, and not stay in http://mushishi.com/auth/callbackthe page, but first into the occurrence of 302 and redirected to the http://mushishi.compage . So redirect_uri value must be with the www (specific reasons for the trouble I was chicken dishes, they did not know, know, leave a message ~ ~)

The second step, after the user to jump, B sites require users to log in and then asked if agreed to give the A site license. The user agrees, then the site will jump back to the B redirect_uri parameter specifies the URL. Jump, returns an authorization code code, like this below.

http://www.mushi.com/auth/callback?code=def50200bb1682081717ff3dec96188294458f971642950dedaf7f7eae&state=elXKJEW6EqmPbAZDnlppmNCE98Uw23HTutPY7poZ

The third step, A to get the website after the authorization code, can be at a rear end, a request token to the B-site.
Routing '/ auth / callback'

// 回调地址,获取 code,并随后发出获取 token 请求
Route::view('/auth/callback', 'auth_callback');

Callback page

Axios method used here, reference axios Chinese document after, url parameters in determining whether to remove the error, no problem asynchronous network requests, to the back post parameters for data exchange

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
    function GetRequest() {
        var url = location.search; //获取url中"?"符后的字串
        var theRequest = {};
        if (url.indexOf("?") !== -1) {
            var str = url.substr(1);
            strs = str.split("&");
            for (var i = 0; i < strs.length; i++) {
                theRequest[strs[i].split("=")[0]] = decodeURI(strs[i].split("=")[1]);
            }
        }
        return theRequest;
    }

    //调用
    var Request = GetRequest();

    if (Request['error']) {
        // 用户未授权处理
        alert(Request['error']);
    }else
    {
        var code = Request['code'];
        var state = Request['state'];

        axios.post('/get/token', {
            params: {
                code,
                state
            }
        })
            .then(function (response) {
                console.log(response.data);
            });
    }
</script>

axios.post Use Case Reference:

// post 数据
let postData = { username: 'user1', password: '123' }
 
axios.post('/login', postData)
    .then(response => {
        // post 成功,response.data 为返回的数据
        // console.log() 方法用于在‘控制台’输出信息。
        console.log(response.data)
    })
    .catch(error => {
        // 请求失败
        console.log(error)
    })

Routing '/ get / token'

Use Guzzle and authorization server for background data exchange

Route::post('/get/token', function (\Illuminate\Http\Request $request) use (
    $clientId,
    $clientSecret
) {
    // csrf 攻击处理
    // 之前存的state
    $state = $request->session()->get('state');
    // 如果判断为false,则抛错,与throw_if相反
    throw_unless(
        strlen($state) > 0 && $state === $request->params['state'],
        InvalidArgumentException::class
    );

    $response
        = (new \GuzzleHttp\Client())->post('http://mushishi.com/oauth/token', [
        'form_params' => [
            'grant_type' => 'authorization_code',
            'client_id' => $clientId,
            'client_secret' => $clientSecret,
            'redirect_uri' => 'http://www.mushi.com/auth/callback',
            'code' => $request->params['code'],
        ],
    ]);

    return json_decode((string)$response->getBody(), true);
});
  1. Refresh access_token
// 刷新 token
Route::view('/refresh/page', 'refresh_page');

Route::post('/refresh', function (\Illuminate\Http\Request $request) use (
    $clientId,
    $clientSecret
) {
    $http = new GuzzleHttp\Client;
    $response = $http->post('http://lishen.com/oauth/token', [
        'form_params' => [
            'grant_type' => 'refresh_token',
            'refresh_token' => $request->params['refresh_token'],
            'client_id' => $clientId,
            'client_secret' => $clientSecret,
        ],
    ]);

    return json_decode((string)$response->getBody(), true);
});
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
    axios.post('/refresh', {
        params: {
        	// 之前给的access_token
            refresh_token: "def502009e634dd59ac4dcd4843be50c3a7a6c76fe0c26a6a948d45b99e393cdf99d1a212a8752d0ce02f4cbc25008972b524336f23b60dfc4198e5413b7e43250126b0d1780afb85443edc1579870e823eedea4313448ffcbc" 
        }
    })
        .then(function (response) {
            console.log(response.data);
        });
</script>
Published 40 original articles · won praise 0 · Views 763

Guess you like

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