交流群 375462817
視頻教程 https://space.bilibili.com/476513143
授權(quán)碼模式
- 嗶哩嗶哩提供一個“微信登陸”的鏈接岛宦,用戶點擊跳轉(zhuǎn)到微信授權(quán)服務(wù)器。
- 用戶根據(jù)微信授權(quán)服務(wù)器提示登陸微信并確認授權(quán)給嗶哩嗶哩污它。
- 微信授權(quán)服務(wù)器返回用戶代理(瀏覽器)一個授權(quán)碼。
- 用戶代理(瀏覽器)把這個授權(quán)碼傳給嗶哩嗶哩扔水。
- 嗶哩嗶哩憑借授權(quán)碼向微信授權(quán)服務(wù)器請求令牌廷没。
- 微信授權(quán)服務(wù)器發(fā)送令牌給嗶哩嗶哩。
服務(wù)器端(微信)
配置
composer create-project --prefer-dist laravel/laravel laravel6
.env 數(shù)據(jù)庫配置
修改數(shù)據(jù)庫默認字符串長度
composer require laravel/passport
Laravel\Passport\HasApiTokens Trait 添加到 App\User 模型中 // 提供一些輔助函數(shù)檢查已認證用戶的令牌和使用范圍
安裝前端必備的東西(腳手架)
下載 node https://nodejs.org/en/
composer require laravel/ui
php artisan ui vue --auth
npm install cnpm -g --registry=https://registry.npm.taobao.org
cnpm install
cnpm run prod
composer require guzzlehttp/guzzle // 偽造 http 請求
// config/auth.php
'api' => [
'driver' => 'passport',
'provider' => 'users',
'hash' => false,
],
php artisan migrate // 創(chuàng)建表來存儲客戶端和 access_token 等
php artisan passport:keys // 加密生成的 access_token
// 注冊路由 AuthServiceProvider
Passport::routes();
Passport::tokensExpireIn(now()->addDays(15)); // access_token 過期時間
Passport::refreshTokensExpireIn(now()->addDays(60)); // refresh_token 過期時間
創(chuàng)建客戶端
php artisan passport:client
第三方應(yīng)用程序(bilibili)
準備
composer create-project --prefer-dist laravel/laravel laravel6
composer require guzzlehttp/guzzle // 偽造 http 請求
web.php
<?php
$clientId = 1;
$clientSecret = '8sGiTDgHb69Y6nTiFImTJO32jm3jB7x2BzMxrhDF';
// bili 登錄頁面
Route::view('/login', 'login');
// 第三方登陸径荔,重定向
Route::get('/lishen/login',
function (\Illuminate\Http\Request $request) use ($clientId) {
$request->session()->put('state', $state = Str::random(40));
$query = http_build_query([
'client_id' => $clientId,
'redirect_uri' => 'http://bili.com/auth/callback',
'response_type' => 'code',
'scope' => '*',
'state' => $state,
]);
return redirect('http://lishen.com/oauth/authorize?'.$query);
});
// 回調(diào)地址督禽,獲取 code,并隨后發(fā)出獲取 token 請求
Route::view('/auth/callback', 'auth_callback');
Route::post('/get/token', function (\Illuminate\Http\Request $request) use (
$clientId,
$clientSecret
) {
// csrf 攻擊處理
$state = $request->session()->pull('state');
throw_unless(
strlen($state) > 0 && $state === $request->params['state'],
InvalidArgumentException::class
);
$response
= (new \GuzzleHttp\Client())->post('http://lishen.com/oauth/token', [
'form_params' => [
'grant_type' => 'authorization_code',
'client_id' => $clientId,
'client_secret' => $clientSecret,
'redirect_uri' => 'http://bili.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);
});
refresh_page
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
axios.post('/refresh', {
params: {
refresh_token: "def502009e634dd59ac4dcd4843be50c3a7a6c76fe0c26a6a948d45b99e393cdf99d1a212a8752d0ce02f4cbc25008972b524336f23b60dfc4198e5413b7e43250126b0d1780afb85443edc1579870e823eedea4313448ffcbe8ca73dc2441e1b1f54d3c0ffc31888e0afeb3b1d4516f6986e540b6a56490dfbfabfe7a88e9fb8539a18cb08f8a2ce10962a3c79e7eed137f137f605cb1ab26254e642750f7f07ebdf17a9ce07a370fabc85e769326cb4fbc9aad402bb69615357766f56e9e26feafac306a7338781317e8baa88e9df9dc0096c92522c8d3cdc1b77cf5273bb0866608575eec5688815d294de22cf8bdf1689cb7e11d6caeb2f3bd80cc57d911b712f79609a45e6e1def42709776c75ca16b56ce6449c25c1660635dfc4a590560db5d2bb52ffcb9be601b8a1ea51c221246815a4f08ed262290cf4fdf0c9c9d357c189f5fa4b9d32c7b9c98a8832666e1ee2eba38b9dc642b02fcc05c38bbdecc"
}
})
.then(function (response) {
console.log(response.data);
});
</script>
auth_callback.blade.php
<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;
}
//調(diào)用
var Request = GetRequest();
if (Request['error']) {
// 用戶未授權(quán)處理
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>