以往,没有做过前后端分离的项目之前,都是服务器渲染的模板,然后用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(); } }
来源:https://www.cnblogs.com/yehuisir/p/11521233.html