Laravel学習ノート(27)laravel 6認証と認証(OAuth 2.0認証コードモード例)
33001 ワード
参考サイトは、サードパーティサーバをシミュレートする2つのサーバ、1つのシミュレート認可サーバ を用意します.ライセンスサーバ(mushishi.com) ComposerパッケージマネージャによるPassportのインストール:laravel/passportでOAuth認証サービスを提供
クライアントとトークンを格納するデータテーブルを作成します.
次に、passport:installコマンドを実行して、セキュリティ・アクセス・トークンの生成に必要な暗号鍵を作成します.また、このコマンドは、アクセス・トークンの生成に使用される「パーソナル・アクセス」クライアント(Personal Access Client)と「パスワード認可」クライアント(Password Grant Client):
PS:生成されたアクセスtoken位置-storage/oauth-private.key
上記のコマンドを実行したら、LaravelPassportHasApiTokens TraitをAppUserモデルに追加してください.このTraitは、認証されたユーザーのトークンと使用範囲を確認するためのモデルに補助関数を提供します.
次に、AuthServiceProviderのbootメソッドでPassport::routes登録トークンに関連するルーティングを呼び出します.
最後に、プロファイルconfig/auth.phpで看守guardsを許可するapiのdriverオプションをpassportに変更します.この調整により、アプリケーションは、受信したAPIの要求を検証するときにPassportのTokenGuardを使用して処理できます.サードパーティサーバ(B局)(mushi.com) 第一歩は、Aサイトにリンクを提供し、ユーザーがクリックするとBサイトにジャンプし、ユーザーデータをAサイトに使用することを許可する.次はAサイトがBサイトをジャンプする概略リンクです.
コード実装:
(1)ルーティング
(2)ビュー
(3)ルーティング
CSRF攻撃方式http_build_query
注意:ここに大きな穴があります!!!リダイレクトされたURL(redirect_uri)は、ジャンプしてwwwではなく
第2ステップでは、ユーザがジャンプすると、Bサイトはユーザにログインを要求し、Aサイトへの権限付与に同意するかどうかを尋ねる.ユーザーが同意した場合(ここではこのステップを無視し、デフォルトでは同意した)Bサイトはredirect_に戻ります.uriパラメータで指定したURL(コールバックアドレス).ジャンプすると、次のように認証コードcodeが返されます.
ステップ3では、Aサイトがライセンスコードを手に入れた後、バックエンドでBサイトにトークンを要求することができます.ルーティング'/auth/callback'
コールバックページ
ここではaxiosメソッドを用い,axios中国語ドキュメントを参照しurlのパラメータを取り出してerrorの有無を判断し,問題なく非同期ネットワーク要求を行い,パラメータpostをバックグラウンドにデータ交換を行う.
axios.post使用例リファレンス:
ルーティング'/get/token'
Guzzleを使用してライセンスサーバとバックグラウンドデータのインタラクションを行うアクセスのリフレッシュtoken
composer require laravel/passport
クライアントとトークンを格納するデータテーブルを作成します.
php artisan migrate
次に、passport:installコマンドを実行して、セキュリティ・アクセス・トークンの生成に必要な暗号鍵を作成します.また、このコマンドは、アクセス・トークンの生成に使用される「パーソナル・アクセス」クライアント(Personal Access Client)と「パスワード認可」クライアント(Password Grant Client):
php artisan passport:install
//
php artisan passport:keys // access_token
php artisan passport:client // , client ID client secret
PS:生成されたアクセスtoken位置-storage/oauth-private.key
上記のコマンドを実行したら、LaravelPassportHasApiTokens TraitをAppUserモデルに追加してください.このTraitは、認証されたユーザーのトークンと使用範囲を確認するためのモデルに補助関数を提供します.
use HasApiTokens, Notifiable;
次に、AuthServiceProviderのbootメソッドでPassport::routes登録トークンに関連するルーティングを呼び出します.
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
最後に、プロファイルconfig/auth.phpで看守guardsを許可するapiのdriverオプションをpassportに変更します.この調整により、アプリケーションは、受信したAPIの要求を検証するときにPassportのTokenGuardを使用して処理できます.
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
https://b.com/oauth/authorize?
response_type=code&
client_id=CLIENT_ID&
redirect_uri=CALLBACK_URL&
scope=read
コード実装:
(1)ルーティング
//
Route::view('/login', 'login');
(2)ビュー
resources/views/login.blade.php
// /mushishi/login, ,
<a href="/mushishi/login"> </a>
(3)ルーティング
CSRF攻撃方式http_build_query
$clientId = 1; // client_id,
$clientSecret = 'T51YiRBezu2QZzmodyTGPKdNJZ4MpeiGPv5PmjiJ'; // client_secret,
//
Route::get('/mushishi/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.mushi.com/auth/callback', // redirect, , , ,
'response_type' => 'code', //
'scope' => '*', //
'state' => session('state'),
]);
//
return redirect('http://mushishi.com/oauth/authorize?'.$query);
});
注意:ここに大きな穴があります!!!リダイレクトされたURL(redirect_uri)は、ジャンプしてwwwではなく
http://mushishi.com/auth/callback
であれば、認証サーバ側が認証を確認してクライアントlaravelページにリダイレクトした後、http://mushishi.com/auth/callback
ページにとどまることなく、先に入ってから302が発生し、http://mushishi.com
ページにリダイレクトする.だからredirect_uriの値は必ずwww(ローカルテストなのでドメイン名を買わなかったので、このような状況になった)第2ステップでは、ユーザがジャンプすると、Bサイトはユーザにログインを要求し、Aサイトへの権限付与に同意するかどうかを尋ねる.ユーザーが同意した場合(ここではこのステップを無視し、デフォルトでは同意した)Bサイトはredirect_に戻ります.uriパラメータで指定したURL(コールバックアドレス).ジャンプすると、次のように認証コードcodeが返されます.
http://www.mushi.com/auth/callback?code=def50200bb1682081717ff3dec96188294458f971642950dedaf7f7eae&state=elXKJEW6EqmPbAZDnlppmNCE98Uw23HTutPY7poZ
ステップ3では、Aサイトがライセンスコードを手に入れた後、バックエンドでBサイトにトークンを要求することができます.ルーティング'/auth/callback'
// , code, token
Route::view('/auth/callback', 'auth_callback');
コールバックページ
ここではaxiosメソッドを用い,axios中国語ドキュメントを参照しurlのパラメータを取り出してerrorの有無を判断し,問題なく非同期ネットワーク要求を行い,パラメータpostをバックグラウンドにデータ交換を行う.
<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使用例リファレンス:
// 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)
})
ルーティング'/get/token'
Guzzleを使用してライセンスサーバとバックグラウンドデータのインタラクションを行う
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);
});
// 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>