一、安裝jwt生成的擴展
這里要注意,一定要安裝此版本,否則下面的Token類可能會發生報錯
composer require lcobucci/jwt=3.3.3
二、將Token.php放入app目錄下
token.php是自己封裝好的類,用于操作上面安裝的擴展
<?php
namespace tools\jwt;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\ValidationData;
/**
* Created by PhpStorm.
* User: asus
* Date: 2019/4/5
* Time: 13:02
*/
class Token
{
private static $_config = [
'audience' => 'http://www.month.com',//接收人
'id' => '3f2g57a92aa',//token的唯一標識,這里只是一個簡單示例
'sign' => 'lajihuishou',//簽名密鑰
'issuer' => 'http://adminapi.month.com',//簽發人
'expire' => 3600*24 //有效期
];
//生成token
public static function getToken($user_id){
//簽名物件
$signer = new Sha256();
//獲取當前時間戳
$time = time();
//設定簽發人、接收人、唯一標識、簽發時間、立即生效、過期時間、用戶id、簽名
$token = (new Builder())->issuedBy(self::$_config['issuer'])
->canOnlyBeUsedBy(self::$_config['audience'])
->identifiedBy(self::$_config['id'], true)
->issuedAt($time)
->canOnlyBeUsedAfter($time-1)
->expiresAt($time + self::$_config['expire'])
->with('user_id', $user_id)
->sign($signer, self::$_config['sign'])
->getToken();
return (string)$token;
}
//從請求資訊中獲取token令牌
public static function getRequestToken()
{
if (empty($_SERVER['HTTP_AUTHORIZATION'])) {
return false;
}
$header = $_SERVER['HTTP_AUTHORIZATION'];
$method = 'bearer';
//去除token中可能存在的bearer標識
return trim(str_ireplace($method, '', $header));
}
//從token中獲取用戶id (包含token的校驗)
public static function getUserId($token = null)
{
$user_id = null;
$token = empty($token)?self::getRequestToken():$token;
if (!empty($token)) {
//為了注銷token 加以下if判斷代碼
$delete_token = cache('delete_token') ?: [];
if(in_array($token, $delete_token)){
//token已被洗掉(注銷)
return $user_id;
}
$token = (new Parser())->parse((string) $token);
//驗證token
$data = new ValidationData();
$data->setIssuer(self::$_config['issuer']);//驗證的簽發人
$data->setAudience(self::$_config['audience']);//驗證的接收人
$data->setId(self::$_config['id']);//驗證token標識
if (!$token->validate($data)) {
//token驗證失敗
return $user_id;
}
//驗證簽名
$signer = new Sha256();
if (!$token->verify($signer, self::$_config['sign'])) {
//簽名驗證失敗
return $user_id;
}
//從token中獲取用戶id
$user_id = $token->getClaim('user_id');
}
return $user_id;
}
}
我是放入了app/tools/jwt下 目錄和檔案名稱可自行改動,需要記住放哪里即可
三、laravel自動加載該類 (同tp5的extend檔案夾)

打開composer.json 找到autoload 在下面的classmap中添加剛才的Token.php檔案
四、封裝token驗證方法
<?php
namespace App\Http\Controllers\Index;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use tools\jwt\Token;
class Api extends Controller
{
//不檢查的 模塊 控制器 方法
protected $no_login = ['Month/Login/loginDo'];
//初始化方法
public function __construct(Request $request)
{
//允許的源域名
header("Access-Control-Allow-Origin: *");
//允許的請求頭資訊
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization");
//允許的請求型別
header('Access-Control-Allow-Methods: GET, POST, PUT,DELETE,OPTIONS,PATCH');
try{
$path = request()->route()->getAction()['controller'];
$newPath = str_replace('@','/',str_replace("\\","/",substr($path,21)));
if(!in_array($newPath, $this->no_login)){
$user_id = Token::getUserId();
//登錄驗證
if(empty($user_id)){
$this->no('未登錄或Token無效', 403);
}
//將獲取的用戶id 設定到請求資訊中
//$request->get($user_id);
//$request->post(['user_id' => $user_id]);
}
}catch(\Exception $e){
$this->no('服務例外,請檢查token令牌', 403);
}
}
/**
* 通用回應
* @param int $code 錯誤碼
* @param string $msg 錯誤描述
* @param array $data 回傳資料
*/
public function response($code=200, $msg='success', $data=[])
{
$res = [
'code' => $code,
'msg' => $msg,
'data' => $data
];
//以下兩行二選一
echo json_encode($res, JSON_UNESCAPED_UNICODE);die;
//json($res)->send();die;
}
/**
* 失敗時回應
* @param string $msg 錯誤描述
* @param int $code 錯誤碼
*/
public function no($msg='fail',$code=500)
{
return $this->response($code, $msg);
}
/**
* 成功時回應
* @param array $data 回傳資料
* @param int $code 錯誤碼
* @param string $msg 錯誤描述
*/
public function ok($data=[], $code=200, $msg='success')
{
return $this->response($code, $msg, $data);
}
}
創建一個API控制器,把想要驗證的控制器繼承API控制器即可驗證token
其中$no_login陣列為不進行驗證的控制器及方法,看注釋就能明白,
五、登錄生成Token
這里以我自己寫的登錄為例,大家參考即可,主要看流程
//登錄功能
public function loginDo(Request $request)
{
try {
$data = $request->validate([
'username' => 'required',
'password' => 'required',
],[
'username.required' => '賬號不能為空',
'username.password' => '密碼不能為空',
]);
}catch (\Exception $e){
return ['code'=>400,'msg'=>array_values($e->errors())[0][0],'data'=>''];
}
//登錄
$login = User::where('username',$data['username'])->first();
if($login['password'] != $data['password']){
return ['code'=>400,'msg'=>'賬號或密碼錯誤','data'=>''];
}
//生成token
$data['token'] = Token::getToken($login->id);
$data['user'] = User::where('id',$login->id)->first();
return ['code'=>'200','msg'=>'登錄成功','data'=>$data];
}
登陸成功后,使用自定義類Token中的getToken方法生成token值,并傳遞到前臺
六、驗證
這里以小程式端為例,獲取到token后將其存到快取中,請求介面時取出,并傳遞
let token = caches.get('token')
wx.request({
url: 'http://www.month.com/api/addOrder',
header:{
authorization:token
},
data:{data:data},
method:'POST',
success:(res)=>{
}
這里注意!微信小程式請求要將token放入header的authorization中,
七、總結
此方法是從tp5的jwt驗證改編而來,如有更好的jwt認證方法,歡迎大家一起評論區討論,
重點要了解jwt的思路,以上代碼只是jwt的生成,以及使用流程,
如對你有幫助,請點贊,收藏+轉發!感謝您的閱讀!
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/286804.html
標籤:其他
