Token 认证流程

  • 作为目前最流行的跨域认证解决方案,JWT(JSON Web Token) 深受开发者的喜爱,主要流程如下:
  • 客户端发送账号和密码请求登录
  • 服务端收到请求,验证账号密码是否通过
  • 验证成功后,服务端会生成唯一的 token,并将其返回给客户端
  • 客户端接受到 token,将其存储在 cookie 或者 localStroge
  • 之后每一次客户端向服务端发送请求,都会通过 cookie 或者header 携带该 token
  • 服务端验证 token 的有效性,通过才返回响应的数据

基于 Token 认证流程

Token 认证优点

  • 支持跨域访问:Cookie 是不允许跨域访问的,这一点对 Token 机制是不存在的,前提是传输的用户认证信息通过 HTTP 头传输
  • 无状态: Token 机制在服务端不需要存储 session 信息,因为 Token 自身包含了所有登录用户的信息,只需要在客户端的 cookie 或本地介质存储状态信息
  • 适用性更广: 只要是支持 http 协议的客户端,就可以使用 token 认证。
  • 无需考虑CSRF: 由于不再依赖 cookie,所以采用 token 认证方式不会发生 CSRF,所以也就无需考虑 CSRF 的防御

JWT 结构

  • 一个 JWT 实际上就是一个字符串,它由三部分组成:头部载荷签名。中间用点 . 分隔成三个部分。注意 JWT 内部是没有换行的。

JWT 结构
  • 头部 / header
  • header 由两部分组成: token 的类型 JWT 和算法名称:HMACSHA256RSA
{
"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 标识
<?php
declare (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
];
  • 注册中间件后,在权限验证中间件中完善验证逻辑
<?php
declare (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);
}
}

实战模拟│JWT 登录认证的更多相关文章

  1. 实战模拟│单点登录 SSO 的实现

    目录 什么是单点登录 单点登录的凭证 父域 Cookie 方式 用户认证中心方式 localstorage方式 什么是单点登录 单点登录: SSO(Single Sign On) 用户只需登录一次,就 ...

  2. 【项目实践】一文带你搞定Session和JWT的登录认证方式

    以项目驱动学习,以实践检验真知 前言 登录认证,估计是所有系统中最常见的功能了,并且也是最基础.最重要的功能.为了做好这一块而诞生了许多安全框架,比如最常见的Shiro.Spring Security ...

  3. OAuth2.0实战!使用JWT令牌认证!

    大家好,我是不才陈某~ 这是<Spring Security 进阶>的第3篇文章,往期文章如下: 实战!Spring Boot Security+JWT前后端分离架构登录认证! 妹子始终没 ...

  4. 基于jwt的用户登录认证

    最近在app的开发过程中,做了一个基于token的用户登录认证,使用vue+node+mongoDB进行的开发,前来总结一下. token认证流程: 1:用户输入用户名和密码,进行登录操作,发送登录信 ...

  5. Luffy之登录认证以及JWT

    1.用户认证 在前面我们已经完成了,前端登录页面的搭建,以及路由分配,现在我们作关于登录认证部分的东西 Django提供了认证系统.认证系统包含: 用户 权限:二元(是/否)标志指示一个用户是否可以做 ...

  6. 基于JWT的Token登录认证(一)

    1.JWT简介 JSON Web Token(缩写 JWT),是目前最流行的跨域认证解决方案. session登录认证方案:用户从客户端传递用户名.密码等信息,服务端认证后将信息存储在session中 ...

  7. JWT实现登录认证实例

    JWT全称JSON Web Token,是一个紧凑的,自包含的,安全的信息交换协议.JWT有很多方面的应用,例如权限认证,信息交换等.本文将简单介绍JWT登录权限认证的一个实例操作. JWT组成 JW ...

  8. 厉害!我带的实习生仅用四步就整合好SpringSecurity+JWT实现登录认证!

    小二是新来的实习生,作为技术 leader,我还是很负责任的,有什么锅都想甩给他,啊,不,一不小心怎么把心里话全说出来了呢?重来! 小二是新来的实习生,作为技术 leader,我还是很负责任的,有什么 ...

  9. 10分钟简单学习net core集成jwt权限认证,快速接入项目落地使用

    什么是JWT JSON Web Token(JWT)是目前最流行的跨域身份验证.分布式登录.单点登录等解决方案. JWT的官网地址:https://jwt.io/ 通俗地来讲,JWT是能代表用户身份的 ...

随机推荐

  1. SSM框架中返回的是字符串还是页面跳转的问题

    如果你在控制器前的注解是@RestController的话,将返回controller方法指定的String值,@RestController注解相当于@ResponseBody和@Controlle ...

  2. Ubuntu22.04搭建PWN环境

    前言 最近尝试在Ubuntu最新的版本22.04版本上搭建PWN环境,有了之前在kali上搭建的经验,总的来说问题不大.但搭建的时候还是有不少地方出错了,好在搭建的过程中不断的拍摄快照,所以整个过程还 ...

  3. Bugku练习题---MISC---easy_nbt

    Bugku练习题---MISC---easy_nbt flag:flag{Do_u_kN0w_nbt?} 解题步骤: 1.观察题目,下载附件 2.通过观察题目描述和压缩包中的文件,发现这个好像是MC的 ...

  4. python数据可视化-matplotlib入门(6)-从文件中加载数据

    前几篇都是手动录入或随机函数产生的数据.实际有许多类型的文件,以及许多方法,用它们从文件中提取数据来图形化. 比如之前python基础(12)介绍打开文件的方式,可直接读取文件中的数据,扩大了我们的数 ...

  5. GO语言学习——切片三 append()方法为切片添加元素、切片的扩容策略、使用copy()函数复制切片、从切片中删除元素

    append()方法为切片添加元素 注意:通过var声明的零值切片可以在append()函数直接使用,无需初始化. var s []int s = append(s, 1, 2, 3) append( ...

  6. Python版本共存、语法、变量和数据类型

    python多版本共存 主要是把两个版本的python解释器的所在路径都加入环境变量当中,之后重新命名python解释器文件名称就好 先拷贝一个启动程序,在进行改名就好 python.exe pyth ...

  7. UNIAPP实现PDA扫码

    目前我接触到了两种方法,以扫码pda安卓采集器(可以直接理解为手机上有个激光扫码)的设置划分. 1.扫描设置 --> 键盘方式输出(键盘类型:物理键盘),注意设置要看具体的型号: 2.扫码设置 ...

  8. AQS源码三视-JUC系列

    AQS源码三视-JUC系列 前两篇文章介绍了AQS的核心同步机制,使用CHL同步队列实现线程等待和唤醒,一个int值记录资源量.为上层各式各样的同步器实现画好了模版,像已经介绍到的ReentrantL ...

  9. autoit 脚本开发踩坑点

    原文 1. 获取不到点击 <input type='file'/> 后弹出的window 根本原因是 _IEAction 阻塞,见第4点 解决办法: ;bad code $oIE = _I ...

  10. 【NodeJS】替换模糊查询字符里包含的正则关键字

    问题:正则匹配时字符串中包含了一些特殊字符,导致查询失败 例如,下面的字符包含了( 和 ),这在正则中属于特殊字符 (-)-magnocurarine 正则中的特殊字符如下图 思路: 1.映射查询字符 ...