实现JWT鉴权机制

一、是什么
JWT(JSON Web Token),本质就是一个字符串书写规范,如下图,作用是用来在用户和服务器之间传递安全可靠的信息

在目前前后端分离的开发过程中,使用token鉴权机制用于身份验证是最常见的方案,流程如下:
- 服务器当验证用户账号和密码正确的时候,给用户颁发一个令牌,这个令牌作为后续用户访问一些接口的凭证
- 后续访问会根据这个令牌判断用户时候有权限进行访问
Token,分成了三部分,头部(Header)、载荷(Payload)、签名(Signature),并以.进行拼接。其中头部和载荷都是以JSON格式存放数据,只是进行了编码

header
每个JWT都会带有头部信息,这里主要声明使用的算法。声明算法的字段名为alg,同时还有一个typ的字段,默认JWT即可。以下示例中算法为HS256
{ "alg": "HS256", "typ": "JWT" }
因为JWT是字符串,所以我们还需要对以上内容进行Base64编码,编码后字符串如下:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
payload
载荷即消息体,这里会存放实际的内容,也就是Token的数据声明,例如用户的id和name,默认情况下也会携带令牌的签发时间iat,通过还可以设置过期时间,如下:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
同样进行Base64编码后,字符串如下:
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
Signature
签名是对头部和载荷内容进行签名,一般情况,设置一个secretKey,对前两个的结果进行HMACSHA25算法,公式如下:
Signature = HMACSHA256(base64Url(header)+.+base64Url(payload),secretKey)
一旦前面两部分数据被篡改,只要服务器加密用的密钥没有泄露,得到的签名肯定和之前的签名不一致
二、如何实现
Token的使用分成了两部分:
- 生成token:登录成功的时候,颁发token
- 验证token:访问某些资源或者接口时,验证token
生成 token
借助第三方库jsonwebtoken,通过jsonwebtoken 的 sign 方法生成一个 token:
第一个参数指的是 Payload
第二个是秘钥,服务端特有
第三个参数是 option,可以定义 token 过期时间
const crypto = require("crypto"),
jwt = require("jsonwebtoken");
// TODO:使用数据库
// 这里应该是用数据库存储,这里只是演示用
let userList = [];
class UserController {
// 用户登录
static async login(ctx) {
const data = ctx.request.body;
if (!data.name || !data.password) {
return ctx.body = {
code: "000002",
message: "参数不合法"
}
}
const result = userList.find(item => item.name === data.name && item.password === crypto.createHash('md5').update(data.password).digest('hex'))
if (result) {
// 生成token
const token = jwt.sign(
{
name: result.name
},
"test_token", // secret
{ expiresIn: 60 * 60 } // 过期时间:60 * 60 s
);
return ctx.body = {
code: "0",
message: "登录成功",
data: {
token
}
};
} else {
return ctx.body = {
code: "000002",
message: "用户名或密码错误"
};
}
}
}
module.exports = UserController;
在前端接收到token后,一般情况会通过localStorage进行缓存,然后将token放到HTTP请求头Authorization 中,关于Authorization 的设置,前面要加上 Bearer ,注意后面带有空格
axios.interceptors.request.use(config => {
const token = localStorage.getItem('token');
config.headers.common['Authorization'] = 'Bearer ' + token; // 留意这里的 Authorization
return config;
})
校验token
使用 koa-jwt 中间件进行验证,方式比较简单
/ 注意:放在路由前面
app.use(koajwt({
secret: 'test_token'
}).unless({ // 配置白名单
path: [/\/api\/register/, /\/api\/login/]
}))
- secret 必须和 sign 时候保持一致
- 可以通过 unless 配置接口白名单,也就是哪些 URL 可以不用经过校验,像登陆/注册都可以不用校验
- 校验的中间件需要放在需要校验的路由前面,无法对前面的 URL 进行校验
获取token用户的信息方法如下:
router.get('/api/userInfo',async (ctx,next) =>{
const authorization = ctx.header.authorization // 获取jwt
const token = authorization.replace('Beraer ','')
const result = jwt.verify(token,'test_token')
ctx.body = result
注意:上述的HMA256加密算法为单秘钥的形式,一旦泄露后果非常的危险
在分布式系统中,每个子系统都要获取到秘钥,那么这个子系统根据该秘钥可以发布和验证令牌,但有些服务器只需要验证令牌
这时候可以采用非对称加密,利用私钥发布令牌,公钥验证令牌,加密算法可以选择RS256
三、优缺点
优点:
- json具有通用性,所以可以跨语言
- 组成简单,字节占用小,便于传输
- 服务端无需保存会话信息,很容易进行水平扩展
- 一处生成,多处使用,可以在分布式系统中,解决单点登录问题
- 可防护CSRF攻击
缺点:
- payload部分仅仅是进行简单编码,所以只能用于存储逻辑必需的非敏感信息
- 需要保护好加密密钥,一旦泄露后果不堪设想
- 为避免token被劫持,最好使用https协议
参考文献
- http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html
- https://blog.wangjunfeng.com/post/golang-jwt/
- https://vue3js.cn/interview/
实现JWT鉴权机制的更多相关文章
- 自定义分布式RESTful API鉴权机制
微软利用OAuth2为RESTful API提供了完整的鉴权机制,但是可能微软保姆做的太完整了,在这个机制中指定了数据持久化的方法是用EF,而且对于用户.权限等已经进行了封装,对于系统中已经有了自己的 ...
- HTTP基本认证和JWT鉴权
一.HTTP基本认证 Basic Authentication——当浏览器访问使用基本认证的网站的时候, 浏览器会提示你输入用户名和密码. http auth的过程: · 客户端发送http请求 · ...
- Spring Boot 鉴权之—— JWT 鉴权
第一:什么是JWT鉴权 1. JWT即JSON Web Tokens,是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519),他可以用来安全的传递信息,因为传递的信息是 ...
- JWT鉴权
一.HTTP基本认证 Basic Authentication--当浏览器访问使用基本认证的网站的时候, 浏览器会提示你输入用户名和密码. http auth的过程: 客户端发送http请求 服务器发 ...
- jwt鉴权学习 (php示例代码)
前段时间听朋友讲起 jwt鉴权,博主我是一脸懵逼,通过朋友坚持不懈的讲解,我终于听懂了,jwt就是登陆token校验嘛 然而事情并不是博主想象的那么简单,在一个艳阳高照,晴空万里的夜晚,博主手贱百度了 ...
- 【十次方微服务后台开发】Day02:加密与JWT鉴权、微服务注册中心、配置中心、熔断器、网关、消息总线、部署与持续集成、容器管理与监控Rancher、influxDB、grafana
一.密码加密与微服务鉴权JWT 1.BCrypt密码加密 Spring Security 提供了BCryptPasswordEncoder类,实现Spring的PasswordEncoder接口使用B ...
- ApiAuthValue鉴权机制总结
一.背景介绍 1.自动化的配置工具autoconfig介绍 项目开发过程中,有些配置会随着运行环境的变化而各不相同.如jdbc驱动的配置,在开发环境可能链接到开发本地的数据库,测试环境则有一套测试专用 ...
- springboot oauth 鉴权之——password鉴权相当于jwt鉴权模式
近期一直在研究鉴权方面的各种案例,这几天有空,写一波总结及经验. 第一步:什么是 OAuth鉴权 OAuth2是工业标准的授权协议.OAuth2取代了在2006创建的原始OAuthTM协议所做的工作. ...
- 通俗化讲解JWT鉴权的使用场景及结构安全
一.基于Session的应用开发的缺陷 在我们传统的B\S应用开发方式中,都是使用session进行状态管理的,比如说:保存登录.用户.权限等状态信息.这种方式的原理大致如下: 用户登陆之后,将状态信 ...
- shiro jwt 构建无状态分布式鉴权体系
一:JWT 1.令牌构造 JWT(json web token)是可在网络上传输的用于声明某种主张的令牌(token),以JSON 对象为载体的轻量级开放标准(RFC 7519). 一个JWT令牌的定 ...
随机推荐
- 案例8:将"picK"的大小写互换
最终输出结果为PICk. 需要先计算两个字母之间的间隔,比如a和A之间的间隔为多少. 然后在将大写字母转换为小写字母,加上间隔的值: 将小写字母转换为大写字母,减去间隔的值. 示例代码如下: #def ...
- 适合新手练习的python开源经典源码
一 前记 python学习离不开三要素: A.基础知识要熟悉 B. 练习源码要够量 C.实战项目要跟上 二 链接 书本的基础就看几本书就可以了,这里给出源码练习的经典开源源码: 该链接集合了pytho ...
- 云流化:XR扩展现实应用发展道路上的新方向
扩展现实的发展已经改变了我们工作.生活和娱乐的方式,而且这才刚刚开始.扩展现实 (Extended reality, XR) 涵盖了沉浸式技术,包括虚拟现实.增强现实和混合现实.从游戏到虚拟制作再到产 ...
- 总体最小二乘法(Total Least Squares)拟合直线
前言 最小二乘法是最小化每个点到直线的垂直误差,由于误差采用的是垂直误差,导致越接近垂直线(平行于\(y\)轴),拟合效果越差,无法拟合垂直线. 通过最小化每个点到直线的距离误差可以解决最小二乘法无法 ...
- drools中使用全局变量
一.背景 在我们编写drools的规则文件的时候,有些时候需要用到全局变量,那么这个该怎么实现呢?有哪些注意事项呢? 二.前置知识 1.语法结构 2.全局变量的特点 使用global来定义全局变量,它 ...
- CentOS7.5安装JDK8
1.下载地址 https://www.oracle.com/java/technologies/javase-jdk8-downloads.html 2.创建文件夹 mkdir /usr/java 3 ...
- List和ObservableCollection的转换
1.我们后台查询全部List数据的时候,前台需要ObservableCollection展示 这个时候List需要转换成ObservableCollection public static Obser ...
- C++设计模式 - 代理模式(Proxy)
接口隔离模式 在组件构建过程中,某些接口之间直接的依赖常常会带来很多问题.甚至根本无法实现.采用添加一层间接(稳定)接口,来隔离本来互相紧密关联的接口是一种常见的解决方案. 典型模式 Facade P ...
- Mybatis-Plus框架的BaseMapper的insert方法和自定义mapper里面的insert方法会用哪个
在Mybatis-Plus框架中,当一个接口继承了BaseMapper接口,并且绑定了一个xml文件时,如果这个接口和xml文件中都定义了相同的方法,那么在调用该方法时,会优先调用xml文件中的方法, ...
- #dp,矩阵乘法#洛谷 5371 [SNOI2019]纸牌
题目 一副纸牌有 \(n\) 种,每种有 \(m\) 张, 现在有 \(k\) 个限制条件形如第 \(k_i\) 种牌至少选 \(a_i\) 张, 一个三元组合法当且仅当其为 \((i,i+1,i+2 ...