以往吴趴,沒有做過前后端分離的項(xiàng)目之前,都是服務(wù)器渲染的模板侮攀,然后用cookie和session進(jìn)行賬號(hào)的權(quán)限驗(yàn)證或者是登錄狀態(tài)的管理锣枝。后來接觸了vue和小程序之后,在進(jìn)行前后端分離的時(shí)候兰英,就會(huì)遇到權(quán)限驗(yàn)證和登錄會(huì)話保存撇叁。因?yàn)镠TTP協(xié)議是開放的,可以任人調(diào)用畦贸。所以陨闹,如果接口不希望被隨意調(diào)用,就需要做訪問權(quán)限的控制薄坏,認(rèn)證是好的用戶趋厉,才允許調(diào)用API。
JWT優(yōu)點(diǎn)
1:服務(wù)端不需要保存?zhèn)鹘y(tǒng)會(huì)話信息胶坠,沒有跨域傳輸問題君账,減小服務(wù)器開銷。
2:jwt構(gòu)成簡(jiǎn)單沈善,占用很少的字節(jié)乡数,便于傳輸。
3:json格式通用闻牡,不同語(yǔ)言之間都可以使用净赴。
jwt由三部分組成:
頭部(header) 載荷(payload) 包含一些定義信息和自定義信息 簽證(signature)
所以這里就會(huì)用到bearer的令牌訪問,就是jwt罩润;定義:為了驗(yàn)證使用者的身份劫侧,需要客戶端向服務(wù)器端提供一個(gè)可靠的驗(yàn)證信息,稱為Token哨啃,這個(gè)token通常由Json數(shù)據(jù)格式組成,通過hash散列算法生成一個(gè)字符串写妥,所以稱為Json Web Token(Json表示令牌的原始值是一個(gè)Json格式的數(shù)據(jù)拳球,web表示是在互聯(lián)網(wǎng)傳播的,token表示令牌珍特,簡(jiǎn)稱JWT)
首先我們從GitHub處用composer require firebase/php-jwt下載firebase/php-jwt祝峻,怎么用composer我就不累述了,我過去的文章里面有安裝教程。
安裝好了之后莱找,我們可以新建一個(gè)user控制來測(cè)試代碼的完整性酬姆,首先我們創(chuàng)建三個(gè)控制方法
Base.php
基礎(chǔ)控制器base.php主要是用來驗(yàn)證每次接受請(qǐng)求的時(shí)候,驗(yàn)證http請(qǐng)求頭里面是否攜帶了token奥溺,如何將token放到請(qǐng)求頭里面辞色,這個(gè)前端會(huì)做的了。
<?php
/**
* Created by PhpStorm.
* User: nobita
* Date: 2/15
* Time: 14:55
*/
namespace app\user\controller;
use think\Request;
use Firebase\JWT\JWT;
use think\Controller;
class Base extends Controller
{
? ? public function _initialize()
? ? {
? ? ? ? parent::_initialize();
? ? ? ? $this->checkToken();
? ? }
? ? public function checkToken()
? ? {
? ? ? ? $header = Request::instance()->header();
? ? ? ? if ($header['authorization'] == 'null'){
? ? ? ? ? ? echo json_encode([
? ? ? ? ? ? ? ? 'status' => 1002,
? ? ? ? ? ? ? ? 'msg' => 'Token不存在,拒絕訪問'
? ? ? ? ? ? ]);
? ? ? ? ? ? exit;
? ? ? ? }else{
? ? ? ? ? ? $checkJwtToken = $this->verifyJwt($header['authorization']);
? ? ? ? ? ? if ($checkJwtToken['status'] == 1001) {
? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? //校驗(yàn)jwt權(quán)限API
? ? protected function verifyJwt($jwt)
? ? {
? ? ? ? $key = md5('nobita');
? ? ? ? // JWT::$leeway = 3;
? ? ? ? try {
? ? ? ? ? ? $jwtAuth = json_encode(JWT::decode($jwt, $key, array('HS256')));
? ? ? ? ? ? $authInfo = json_decode($jwtAuth, true);
? ? ? ? ? ? $msg = [];
? ? ? ? ? ? if (!empty($authInfo['user_id'])) {
? ? ? ? ? ? ? ? $msg = [
? ? ? ? ? ? ? ? ? ? 'status' => 1001,
? ? ? ? ? ? ? ? ? ? 'msg' => 'Token驗(yàn)證通過'
? ? ? ? ? ? ? ? ];
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? $msg = [
? ? ? ? ? ? ? ? ? ? 'status' => 1002,
? ? ? ? ? ? ? ? ? ? 'msg' => 'Token驗(yàn)證不通過,用戶不存在'
? ? ? ? ? ? ? ? ];
? ? ? ? ? ? }
? ? ? ? ? ? return $msg;
? ? ? ? } catch (\Firebase\JWT\SignatureInvalidException $e) {
? ? ? ? ? ? echo json_encode([
? ? ? ? ? ? ? ? 'status' => 1002,
? ? ? ? ? ? ? ? 'msg' => 'Token無效'
? ? ? ? ? ? ]);
? ? ? ? ? ? exit;
? ? ? ? } catch (\Firebase\JWT\ExpiredException $e) {
? ? ? ? ? ? echo json_encode([
? ? ? ? ? ? ? ? 'status' => 1003,
? ? ? ? ? ? ? ? 'msg' => 'Token過期'
? ? ? ? ? ? ]);
? ? ? ? ? ? exit;
? ? ? ? } catch (Exception $e) {
? ? ? ? ? ? return $e;
? ? ? ? }
? ? }
}
Login.php
登錄控制器浮定,只要是用來驗(yàn)證用戶輸入的賬號(hào)密碼是否匹配數(shù)據(jù)庫(kù)的信息相满,如果匹配的話,就申請(qǐng)token桦卒,并且返回token給前端儲(chǔ)存在本地立美,每次請(qǐng)求的時(shí)候把token假如到請(qǐng)求頭里面
<?php
/**
* Created by PhpStorm.
* User: nobita
* Date: 2/15
* Time: 14:55
*/
namespace app\user\controller;
use app\common\model\nobita\Test as TestModel;
use Firebase\JWT\JWT;
class Login
{
? ? public function index()
? ? {
? ? ? ? $data = input('post.');
? ? ? ? $username = htmlspecialchars($data['username']);
? ? ? ? $password = htmlspecialchars($data['password']);
? ? ? ? $user = TestModel::where('username', $username)->find();
? ? ? ? if (!empty($user)) {
? ? ? ? ? ? if ($username === $user['username'] && $password === $user['password']) {
? ? ? ? ? ? ? ? $msg = [
? ? ? ? ? ? ? ? ? ? 'status' => 1001,
? ? ? ? ? ? ? ? ? ? 'msg' => '登錄成功',
? ? ? ? ? ? ? ? ? ? 'jwt' => self::createJwt($user['id'])
? ? ? ? ? ? ? ? ];
? ? ? ? ? ? ? ? return $msg;
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? return [
? ? ? ? ? ? ? ? ? ? 'status' => 1002,
? ? ? ? ? ? ? ? ? ? 'msg' => '賬號(hào)密碼錯(cuò)誤'
? ? ? ? ? ? ? ? ];
? ? ? ? ? ? }
? ? ? ? } else {
? ? ? ? ? ? return [
? ? ? ? ? ? ? ? 'status' => 1002,
? ? ? ? ? ? ? ? 'msg' => '請(qǐng)輸入賬號(hào)密碼'
? ? ? ? ? ? ];
? ? ? ? }
? ? }
? ? public function createJwt($userId)
? ? {
? ? ? ? $key = md5('nobita'); //jwt的簽發(fā)密鑰,驗(yàn)證token的時(shí)候需要用到
? ? ? ? $time = time(); //簽發(fā)時(shí)間
? ? ? ? $expire = $time + 14400; //過期時(shí)間
? ? ? ? $token = array(
? ? ? ? ? ? "user_id" => $userId,
? ? ? ? ? ? "iss" => "https://199508.com",//簽發(fā)組織
? ? ? ? ? ? "aud" => "https://199508.com", //簽發(fā)作者
? ? ? ? ? ? "iat" => $time,
? ? ? ? ? ? "nbf" => $time,
? ? ? ? ? ? "exp" => $expire
? ? ? ? );
? ? ? ? $jwt = JWT::encode($token, $key);
? ? ? ? return $jwt;
? ? }
}
User.php
用來驗(yàn)證代碼的完整性
<?php
/**
* Created by PhpStorm.
* User: nobita
* Date: 2/15
* Time: 15:24
*/
namespace app\user\controller;
use think\Request;
use app\common\model\nobita\Test as TestModel;
class User extends Base //繼承基礎(chǔ)控制器
{
? ? public function index()
? ? {
? ? ? ? return TestModel::all();
? ? }
}