ThinkPHP5使用jwt進行會話驗證


以往,沒有做過前后端分離的項目之前,都是服務器渲染的模板,然后用cookie和session進行賬號的權限驗證或者是登錄狀態的管理。后來接觸了vue和小程序之后,在進行前后端分離的時候,就會遇到權限驗證和登錄會話保存。因為HTTP協議是開放的,可以任人調用。所以,如果接口不希望被隨意調用,就需要做訪問權限的控制,認證是好的用戶,才允許調用API。

JWT優點

1:服務端不需要保存傳統會話信息,沒有跨域傳輸問題,減小服務器開銷。

2:jwt構成簡單,占用很少的字節,便於傳輸。

3:json格式通用,不同語言之間都可以使用。

jwt由三部分組成:

頭部(header) 載荷(payload) 包含一些定義信息和自定義信息 簽證(signature)

所以這里就會用到bearer的令牌訪問,就是jwt;定義:為了驗證使用者的身份,需要客戶端向服務器端提供一個可靠的驗證信息,稱為Token,這個token通常由Json數據格式組成,通過hash散列算法生成一個字符串,所以稱為Json Web Token(Json表示令牌的原始值是一個Json格式的數據,web表示是在互聯網傳播的,token表示令牌,簡稱JWT)

首先我們從GitHub處用composer require firebase/php-jwt下載firebase/php-jwt,怎么用composer我就不累述了,我過去的文章里面有安裝教程。

安裝好了之后,我們可以新建一個user控制來測試代碼的完整性,首先我們創建三個控制方法

Base.php

基礎控制器base.php主要是用來驗證每次接受請求的時候,驗證http請求頭里面是否攜帶了token,如何將token放到請求頭里面,這個前端會做的了。

<?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;
            }
        }
    }

    //校驗jwt權限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驗證通過'
                ];
            } else {
                $msg = [
                    'status' => 1002,
                    'msg' => 'Token驗證不通過,用戶不存在'
                ];
            }
            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

登錄控制器,只要是用來驗證用戶輸入的賬號密碼是否匹配數據庫的信息,如果匹配的話,就申請token,並且返回token給前端儲存在本地,每次請求的時候把token假如到請求頭里面

<?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' => '賬號密碼錯誤'
                ];
            }
        } else {
            return [
                'status' => 1002,
                'msg' => '請輸入賬號密碼'
            ];
        }
    }

    public function createJwt($userId)
    {
        $key = md5('nobita'); //jwt的簽發密鑰,驗證token的時候需要用到
        $time = time(); //簽發時間
        $expire = $time + 14400; //過期時間
        $token = array(
            "user_id" => $userId,
            "iss" => "https://199508.com",//簽發組織
            "aud" => "https://199508.com", //簽發作者
            "iat" => $time,
            "nbf" => $time,
            "exp" => $expire
        );
        $jwt = JWT::encode($token, $key);
        return $jwt;
    }
}

User.php

用來驗證代碼的完整性

<?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 //繼承基礎控制器
{
    public function index()
    {
        return TestModel::all();
    }
}

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM