目前,前後端分離時越來越多了,後端只需要提供一個Api介面解可以了,但是,登入問題怎麼解決呢?下面就來介紹如何使用laravel有效解決登入問題。
思路流程
- 由於在前端頁面,每個使用者肯定都有自己單獨的模組,所以我們後端需要返回各自使用者的資料。
- 使用者首先進行登入,後臺利用Passport官方包,給該使用者返回一個access_token(暗號)
- 使用者獲取到access_token(暗號),然後存在本地的localstorage裡或者是vuex的state裡(前提時用vue的,其他框架同理)。
- 然後在使用者模組訪問後臺的時候按要求帶上access_token訪問。
- 後臺就可以根據access_token查到對應的使用者,查出資料,返回給前端。
安裝
- 使用composer安裝Passport:
composer require laravel/passport
複製程式碼
- 接下來,將 Passport 的服務提供者註冊到配置檔案 config/app.php 的 providers 陣列中:
Laravel\Passport\PassportServiceProvider::class,
複製程式碼
- 而Passport服務時官方包,有自帶的資料庫遷移目錄,所以直接可以用命令執行遷移來自動建立儲存各種資訊的資料表
php artisan migrate
複製程式碼
- 然後建立密碼授權客戶端
php artisan passport:client --password
# 建立了client_id和client_secret,前端登入驗證的時候必須把這兩個玩意帶著喲
複製程式碼
- 建立了密碼授權客戶端就可以按以下要求獲取
access_token
了。以vue+axios舉例
(這裡為了防止不太會axios的小夥伴,在main.js進行配置一下。)
import axios from 'axios'
Vue.prototype.axios = axios
//安裝好axios包之後,在根目錄的main.js裡新增上面的兩行程式碼,注意放到引入Vue的下面。
複製程式碼
你肯定會問傳到後臺的data client_id
和 client_secret
是什麼?
說簡單點,其實就是表示你前端要用到這個passport來驗證的一個暗號。
- 這個時候你就需要打以下命令獲取這兩玩意。
php artisan passport:keys
# 獲取到了,然後記住這兩個東西,沒有記住,也可以在資料庫裡的oauth_clients表裡去看喲
複製程式碼
以上需要跑的命令基本就跑完了 , 接下來就時配置方面的了。
配置
- 首先, 得讓安裝的Passport服務在認證服務提供
AuthServiceProvider
的boot
方法中呼叫Passport::routes
函式。如果令牌需要有效期和重新整理時間看下圖:
public function boot()
{
$this->registerPolicies(); //註冊
Passport::routes(); //認證的路由
Passport::tokensExpireIn(Carbon::now()->addHours(3)); //令牌有效期3小時
Passport::refreshTokensExpireIn(Carbon::now()->addDays(30)); //令牌重新整理時間30
}
複製程式碼
如果覺得時間過長或者過短,您還可以使用addMinutes()
或者時addMonths()
都可以的。
- 最後,將配置檔案
config/auth.php
中授權看守器guards
的api
的driver
選項改為passport
。此調整會讓你的應用程式在在驗證傳入的 API 的請求時使用 Passport 的TokenGuard
來處理:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
複製程式碼
設定中介軟體和路由
- 首先需要在
app/Http/Kernel.php
的$routeMiddleware
變數中新增新的中介軟體:
protected $routeMiddleware = [
'client.credentials' => \Laravel\Passport\Http\Middleware\CheckClientCredentials::class,
];
複製程式碼
- 然後在需要的模組路由
routes/api.php
前面加上這個中介軟體。
//使用者
Route::get('/customer', 'customerController@index')->middleware('client.credentials');
複製程式碼
前端的登入測試
後端已經基本都配置好了,那麼再就需要前端進行登入按要求傳送請求給後端了。
//前面已經說了,我們會用到client_id和client_secret這個時候就要派上用場了喲。
//請看以下html的程式碼
<template>
<input type="email" v-model="userInfo.email" placeholder="請輸入郵箱">
<input type="password" v-model="userInfo.password" placeholder="請輸入密碼">
<button @click.prevent="submit">登 錄</button>
</template>
//請看vue裡的程式碼
<script>
export default {
data() {
return {
userInfo: {
email: '',
password: ''
}
}
},
methods: {
submit() {
//將資料配置好
const data = {
grant_type: 'password', //oauth的模式
client_id: 1, //上面所說的client_id
client_secret: '5wq3G7wv0ZuK7Qj6aFtwZaX6XyfLLa8hLSDDJyAB',//同上
username: this.userInfo.email,
password: this.userInfo.password,
}
this.axios.post('http://your domain/oauth/token', data)
.then(res => {
if(res.status == 200) { //如果成功了
//將收到的token_type和access_token存到localStorage裡
localStorage.token_type = res.data.token_type
localStorage.token_token = res.data.access_token
//登入成功跳轉到你想跳轉的地址
...
}
})
}
}
}
</script>
複製程式碼
通過這樣的請求,只要後端配置好了,基本就能收到以下的json
當然從我們上面的程式碼可以看出,我們也已經將重要的東西access_token
和token_type
存了起來啦。
axios的配置
終於把令牌access_token和令牌型別token_type拿到手了。那麼後面,我們前端只要涉及到api認證的請求(我們這裡拿個人中心做例子)就應該把這兩個玩意帶著傳送給後端,這樣後端就可以分辨是哪個使用者的請求了,也就可以返回相應的資訊了。
好了,這個時候就需要配置一下axios了喲,把以後的請求都帶上這兩玩意就是了,簡單、舒服。請看以下的配置,我們這裡單獨建立一個http.js重新配置了axios。
//#建立http.js檔案
import axios from 'axios'
import router from '@/router'
// axios 配置
axios.defaults.timeout = 5000;
// axios.defaults.baseURL = 'https://api.github.com';
// http request 攔截器
axios.interceptors.request.use(
config => { //將所有的axios的header里加上token_type和access_token
config.headers.Authorization = `${localStorage.token_type} ${localStorage.access_token}`;
return config;
},
err => {
return Promise.reject(err);
});
// http response 攔截器
axios.interceptors.response.use(
response => {
return response;
},
error => {
// 401 清除token資訊並跳轉到登入頁面
if (error.response.status == 401) {
alert('登入資訊已失效,請重新登入')
router.replace({ //如果失敗,跳轉到登入頁面
name: 'login'
})
}
return Promise.reject(error.response.data)
});
export default axios; //然後再次export出去,嘿嘿 main.js那裡就得改改咯
複製程式碼
//#main.js檔案
//將原來上面配置的 import axios from 'axios'
//改成
import axios from './http' //這裡我的http.js是和main.js同一目錄。
複製程式碼
個人使用者頁面測試
都配置好啦,接下來,拿使用者中心頁面來獲取使用者的資訊了。
<script>
export default {
data() {
return {
user[]
}
},
created() {
this.getUser()
},
methods: {
getUser() {
this.axios.get('http://your domain/api/customer')
.then(res => {
console.log(res)
this.user = res.data //將得到的使用者資訊,傳給user。
})
}
}
}
</script>
複製程式碼
哇,終於獲取到登入的那個使用者的使用者資訊了喲。不過......
後臺怎麼解析token拿到使用者資訊。
還有最後的一個問題, 後臺根據怎麼根據前端傳送的
access_token
來查詢到使用者資訊傳送給前端呢。
開啟你的User模型User.php,通常放在Http目錄下。
在檔案裡的上面加上use Laravel\Passport\HasApiTokens;
然後User類裡,也別忘了加上
use Notifiable,HasApiTokens;
這個就是用來根據token來獲取user資訊的。
#CustomerController@index方法裡。
$user = auth('api')->user();
return $user; //成功將使用者資訊返回給前端啦。
複製程式碼
就這樣完美結束啦。歡迎吐槽~