記錄學習中遇到的各種奇奇怪怪的問題
現在jwt和配置jwt我就不寫了
1.後臺登入方法
public function login(Request $request){
$arr = $request->only(['email','password']);
if(empty($arr)){
return $this->response->array([
'msg'=>'is null',
'code'=>403,
'data' => [],
]);
}
$token = Auth::guard('api')->attempt($arr); //獲取token
//未獲得token時返回錯誤
if(!$token){
return $this->responseinfo('error',403,[]);
}
//返回當前使用者
$userAuth =Auth::guard('api')->user();
//查詢使用者資訊
$user = Login::find($userAuth->id);
$user->update([$user->updated_at = time()]);
return $this->response->array([
'msg'=>'success',
'token' => 'Bearer '.$token,
'code' => 200
]);
}
這裡有一個值得注意的地方,也是我踩過的一個坑:返回的token必須在前面加入“Bearer +Token” ,這裡Bearer和Token之間有一個空格
2.前端VUE接收
axios.post('/api/index/login', {
email: this.email,
password: this.password
})
.then((response) =>{
if(response.data.code === 200 ){
let token = response.data.token
Toast.success('登入成功')
window.localStorage.setItem('token',token)
this.$store.commit('setToken',token)
return this.$router.push('/myhome')
}else{
Toast.fail('賬戶密碼錯誤')
}
})
這裡是我的前端請求登入方法,在這裡需要在後端成功返回之後,將token值儲存在本地(localStorage.setItem),因為我這裡用的vantui框架,所以要加上windows. 另外將token儲存至vuex中。
3.vuex的配置
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
// 儲存公共資料 在設定vuex中的初值時,先從本地儲存中取,如果取不到,則初始為空
tokenInfo: window.localStorage.getItem('token') || {}
},
mutations: {
setToken(state, tokenObj) {
state.tokenInfo = tokenObj
// 因為重新整理會丟失所以進行持久化 呼叫storage檔案裡方法
window.localStorage.setItem('tokenInfo', tokenObj)
}
},
actions: {},
modules: {}
})
4 axios的配置
//請求頭新增token
_axios.interceptors.request.use(
function(config) {
let token = store.state.tokenInfo //獲取token
if (token) {
config.headers.Authorization = token //在請求頭中加入token
}
return config;
},
function(error) {
// Do something with request error
return Promise.reject(error);
}
);
這樣你的登入方法就做完了,在登入後跳轉至首頁時,首頁傳送請求來獲取使用者資訊,就會在header中攜帶token了。
下面來看一下token令牌的驗證
1.首頁傳送請求獲取使用者資訊,在hearder中攜帶Token令牌
新建路由中介軟體中介軟體:RefreshTokenMiddleware , 並完成配置
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Facades\JWTAuth;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
class RefreshTokenMiddleware extends BaseMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
// 檢查此次請求中是否帶有 token,如果沒有則丟擲異常。在這裡如果你的Token沒有新增Bearer ,將會丟擲異常檢測不到token令牌
$this->checkForToken($request);
// 使用 try 包裹,以捕捉 token 過期所丟擲的 TokenExpiredException 異常
try {
// 檢測使用者的登入狀態,如果正常則通過
if ($this->auth->parseToken()->authenticate()) {
return $next($request);
}
throw new UnauthorizedHttpException('jwt-auth', '未登入');
} catch (TokenExpiredException $exception) {
// 此處捕獲到了 token 過期所丟擲的 TokenExpiredException 異常,我們在這裡需要做的是重新整理該使用者的 token 並將它新增到響應頭中
try {
// 重新整理使用者的 token
$token = $this->auth->refresh();
// 使用一次性登入以保證此次請求的成功
Auth::guard('api')->onceUsingId($this->auth->manager()->getPayloadFactory()->buildClaimsCollection()->toPlainArray()['sub']);
} catch (JWTException $exception) {
// 如果捕獲到此異常,即代表 refresh 也過期了,使用者無法重新整理令牌,需要重新登入。
throw new UnauthorizedHttpException('jwt-auth', $exception->getMessage());
}
}
// 在響應頭中返回新的 token
return $this->setAuthenticationHeader($next($request), $token);
}
}
使用中介軟體,並配置路由:
寫上你控制器方法,你就可以正常訪問了,並且你的每次請求都是攜帶token令牌的,不過這裡有一個我還在做的事情,當token過期瀏覽器返回401時,vue的axios要接收後端返回的請求頭裡的新token,並對舊的token進行替換,然後再次請求剛剛請求失敗的api,我也還在學習,當功能完成時我會再將我的程式碼貼出來
結語
記錄自己學習的過程。
本作品採用《CC 協議》,轉載必須註明作者和本文連結