当前位置:网站首页>实战模拟│JWT 登录认证
实战模拟│JWT 登录认证
2022-07-04 19:49:00 【华为云】
Token 认证流程
- 作为目前最流行的跨域认证解决方案,
JWT(JSON Web Token)深受开发者的喜爱,主要流程如下: - 客户端发送账号和密码请求登录
- 服务端收到请求,验证账号密码是否通过
- 验证成功后,服务端会生成唯一的
token,并将其返回给客户端 - 客户端接受到
token,将其存储在cookie或者localStroge中 - 之后每一次客户端向服务端发送请求,都会通过
cookie或者header携带该token - 服务端验证
token的有效性,通过才返回响应的数据

Token 认证优点
- 支持跨域访问:
Cookie是不允许跨域访问的,这一点对Token机制是不存在的,前提是传输的用户认证信息通过HTTP头传输 - 无状态:
Token机制在服务端不需要存储session信息,因为Token自身包含了所有登录用户的信息,只需要在客户端的cookie或本地介质存储状态信息 - 适用性更广: 只要是支持
http协议的客户端,就可以使用token认证。 - 无需考虑CSRF: 由于不再依赖
cookie,所以采用token认证方式不会发生CSRF,所以也就无需考虑CSRF的防御
JWT 结构
- 一个
JWT实际上就是一个字符串,它由三部分组成:头部、载荷与签名。中间用点.分隔成三个部分。注意JWT内部是没有换行的。

- 头部 / header
header由两部分组成:token的类型JWT和算法名称:HMAC、SHA256、RSA
{ "alg": "HS256", "typ": "JWT"}- 载荷 / Payload
Payload部分也是一个JSON对象,用来存放实际需要传递的数据。JWT指定七个默认字段供选择。- 除了默认字段之外,你完全可以添加自己想要的任何字段,一般用户登录成功后,就将用户信息存放在这里
iss:发行人exp:到期时间sub:主题aud:用户nbf:在此之前不可用iat:发布时间jti:JWT ID用于标识该JWT{ "iss": "xxxxxxx", "sub": "xxxxxxx", "aud": "xxxxxxx", "user": [ 'username': '极客飞兔', 'gender': 1, 'nickname': '飞兔小哥' ] }- 签名 / Signature
- 签名部分是对上面的 头部、载荷 两部分数据进行的数据签名
- 为了保证数据不被篡改,则需要指定一个密钥,而这个密钥一般只有你知道,并且存放在服务端
- 生成签名的代码一般如下:
// 其中secret 是密钥String signature = HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)JWT 基本使用
- 客户端收到服务器返回的
JWT,可以储存在Cookie里面, 也可以储存在localStorage - 然后 客户端每次与服务器通信,都要带上这个
JWT - 把
JWT保存在Cookie里面发送请求,这样不能跨域 - 更好的做法是放在
HTTP请求的头信息Authorization字段里面
fetch('license/login', { headers: { 'Authorization': 'X-TOKEN' + token }})实战:使用 JWT 登录认证
这里使用
ThinkPHP6整合JWT登录认证进行实战模拟安装 JWT 扩展
composer require firebase/php-jwt- 封装生成 JWT 和解密方法
<?php/** * Desc: JWT认证 * Author: autofelix * Time: 2022/07/04 */namespace app\services;use app\Helper;use Firebase\JWT\JWT;use Firebase\JWT\Key;class JwtService{ protected $salt; public function __construct() { //从配置信息这种或取唯一字符串,你可以随便写比如md5('token') $this->salt = config('jwt.salt') || "autofelix"; } // jwt生成 public function generateToken($user) { $data = array( "iss" => 'autofelix', //签发者 可以为空 "aud" => 'autofelix', //面象的用户,可以为空 "iat" => Helper::getTimestamp(), //签发时间 "nbf" => Helper::getTimestamp(), //立马生效 "exp" => Helper::getTimestamp() + 7200, //token 过期时间 两小时 "user" => [ // 记录用户信息 'id' => $user->id, 'username' => $user->username, 'truename' => $user->truename, 'phone' => $user->phone, 'email' => $user->email, 'role_id' => $user->role_id ] ); $jwt = JWT::encode($data, md5($this->salt), 'HS256'); return $jwt; } // jwt解密 public function chekToken($token) { JWT::$leeway = 60; //当前时间减去60,把时间留点余地 $decoded = JWT::decode($token, new Key(md5($this->salt), 'HS256')); return $decoded; }}- 用户登录后,生成 JWT 标识
<?phpdeclare (strict_types=1);namespace app\controller;use think\Request;use app\ResponseCode;use app\Helper;use app\model\User as UserModel;use app\services\JwtService;class License{ public function login(Request $request) { $data = $request->only(['username', 'password', 'code']); // ....进行验证的相关逻辑... $user = UserModel::where('username', $data['username'])->find(); // 验证通过生成 JWT, 返回给前端保存 $token = (new JwtService())->generateToken($user); return json([ 'code' => ResponseCode::SUCCESS, 'message' => '登录成功', 'data' => [ 'token' => $token ] ]); }}- 中间件验证用户是否登录
- 在
middleware.php注册中间件
<?php// 全局中间件定义文件return [ // ...其他中间件 // JWT验证 \app\middleware\Auth::class];- 注册中间件后,在权限验证中间件中完善验证逻辑
<?phpdeclare (strict_types=1);namespace app\middleware;use app\ResponseCode;use app\services\JwtService;class Auth{ private $router_white_list = ['login']; public function handle($request, \Closure $next) { if (!in_array($request->pathinfo(), $this->router_white_list)) { $token = $request->header('token'); try { // jwt 验证 $jwt = (new JwtService())->chekToken($token); } catch (\Throwable $e) { return json([ 'code' => ResponseCode::ERROR, 'msg' => 'Token验证失败' ]); } $request->user = $jwt->user; } return $next($request); }}边栏推荐
- Win11无法将值写入注册表项如何解决?
- [ismb2022 tutorial] the picture shows the precision medicine of learning. Marinka zitnik, Harvard University, keynote speaker, with 87 ppt
- 接口設計時的一些建議
- 【申博攻略】六.如何联系心仪的博导
- Win11共享文件打不开怎么办?Win11共享文件打不开的解决方法
- vim异步问题
- VIM asynchronous problem
- Aiming at the "amnesia" of deep learning, scientists proposed that based on similarity weighted interleaved learning, they can board PNAS
- Hash哈希竞猜游戏系统开发如何开发丨哈希竞猜游戏系统开发(多套案例)
- 记录线上bug解决list(未完待续7/4)
猜你喜欢

Jiuqi ny8b062d MCU specification /datasheet

九齐NY8B062D MCU规格书/datasheet

《动手学深度学习》(三) -- 卷积神经网络 CNN

Qt五子棋人机对战画棋子之QPainter的使用误区总结

Flet教程之 04 FilledTonalButton基础入门(教程含源码)

Leetcode+ 81 - 85 monotone stack topic

Win11共享文件打不开怎么办?Win11共享文件打不开的解决方法

工厂从自动化到数字孪生,图扑能干什么?

Flet教程之 05 OutlinedButton基础入门(教程含源码)

【观察】联想:3X(1+N)智慧办公解决方案,释放办公生产力“乘数效应”
随机推荐
word中插入图片后,图片上方有一空行,且删除后布局变乱
Form组件常用校验规则-1(持续更新中~)
接口设计时的一些建议
Some suggestions for interface design
Jekins initialization password not found or not found
测试员的算法面试题-找众数
acwing 3302. Expression evaluation
NLP, vision, chip What is the development direction of AI? Release of the outlook report of Qingyuan Association [download attached]
栈:如何实现有效括号的判断?
哈希表、哈希函数、布隆过滤器、一致性哈希
Jmeter 之压测入门
MySQL --- 数据库查询 - 聚合函数的使用、聚合查询、分组查询
Record the online bug solving list (unfinished to be continued 7/4)
Flet教程之 08 AppBar工具栏基础入门(教程含源码)
HMS Core 机器学习服务
电脑页面不能全屏怎么办?Win11页面不能全屏的解决方法
jekins初始化密码没有或找不到
Vue cleans up the keepalive cache scheme in a timely manner
Automatic generation of interface automatic test cases by actual operation
企业数字化转型最佳实践案例:基于云的数字化平台系统安全措施简介与参考