学习目标:
十分钟学会JWT
学习内容:
1、 JWT的概述 2、 JWT的起源 3、 JWT的构成 4、 搭建JWT
学习时间:
2021年12月28日
学习产出:
1、 技术笔记 1 遍 2、CSDN 技术博客 1 篇
JWT概述
Json web token (JWT),是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。定义的一种简介的,自包含的方法用于通信双方之间以JSON对象的形式安全的传递信息。因为数字签名的存在,这些信息是 可信的 ,JWT可以使用HMAC算法或者是RSA的公司秘钥进行签名。
起源
说起JWT,我们应该来谈一谈基于token的认证和传统的session认证的区别。
传统的session认证
http协议本身是一种无状态的协议,而这就意味着如果用户向我们的应用提供了用户名和密码来进行用户认证,那么下一次请求时,用户还要再一次进行用户认证才行,因为根据http协议,我们并不能知道是哪个用户发出的请求,所以为了让我们的应用能识别是哪个用户发出的请求,我们只能在服务器存储一份用户登录的信息,这份登录信息会在响应时传递给浏览器,告诉其保存为cookie,以便下次请求时发送给我们的应用,这样我们的应用就能识别请求来自哪个用户了,这就是传统的基于session认证。
? 但是这种基于session的认证使应用本身很难得到扩展,随着不同客户端用户的增加,独立的服务器已无法承载更多的用户,而这时候基于session认证应用的问题就会暴露出来。
基于session认证所显露的问题
session:每个用户经过我们的应用认证之后,我们的应用都要在服务端做一次记录,以便用户下次请求的鉴别,通常而言session都是保存在内存之重的,而随着认证用户的增多,服务端的开销会明显增大。
扩展性:用户认证之后,服务端做认证记录,如果认证的记录被保存在内存中的话,这意味着用户下次请求还必须要请求在这台服务器上,这样才能拿到授权的资源,这样在分布式的应用上,相应的限制了负载均衡的能力。这也就意味着限制了应用的扩展能力。
CSRF(跨站请求伪造):因为是基于cookie来进行用户识别的,cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。
基于token的鉴权机制
基于token的鉴权机制类似于http协议也是无状态的,它不需要在服务端去保留用户的认证信息或者会话信息。这就意味着基于token认证机制的应用不需要去考虑用户在哪一台服务器登录了,这就为应用的扩展提供了遍历。
token生成的流程:
- 用户使用账号和密码发出post请求;
- 服务器使用私钥创建一个jwt;
- 服务器返回这个jwt给浏览器;
- 浏览器将该jwt串在请求头中像服务器发送请求;
- 服务器验证该jwt;
- 返回响应的资源给浏览器。
JWT主要应用场景
身份认证在这种场景下,一旦用户完成了登录,在接下来的每个请求中包含JWT,可以用来验证用户的身份以及对路由,服务和资源的访问权限进行验证。由于它的开销非常小,可以轻松的在不同域名的系统中传递,所有目前在**单点登录(SSO)**中比较广泛的使用了该技术。信息交换在通信双方之间使用JWT对数据进行编码是一种非常安全的方式,由于他的信息是经过签名的,可以确保发送者发送的信息是没有经过伪造的。
优点
1、简洁
? 可以通过URL,POST参数或者在HTTO header发送,因为数据量小,传输速度也可以很快。
2、自包含
? 负载中 包含了所有用户所需要的信息,避免了多次查询数据库
3、因为token是以JSON加密的形式保存在客户端的,所以JWT是跨语言的,原则上任何web形式都支持。
4、不需要在服务端保存会话信息,特别适用于分布式微服务。
JWT构成
JWT由三部分构成:头部(header)、荷载(payload,用户的信息)、签证(signature)
这三段信息文本用 . 连接一起就构成了JWT字符串,就像:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
第一部分
header jwt的头部承载两部分信息
? 声明类型,这里是jwt
? 声明加密的算法 通常直接使用 HMAC HS256
完整的头部就像下面这样的JSON: {
? ‘typ’:‘JWT’,
? ‘alg’:‘HS256’
? }
然后将头部进行base64转码,构成了第一部分。
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
10010101 01010101
100101 010101 010100
第二部分
playload
荷载就是存放有效信息的地方。这个名字像是特指飞机上承载的货品,这些有效信息包含三个部分
? 注册中注册的声明
? 公共的声明
? 私有的声明
? 公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务 需要的必要信息,但不建议添加敏感信息(例如密码),因为该部分在客户端可解密 id 用户名 头像名
定义一个payload
? {
? “sub”:“1234567890”,
? “name”:“John Doe”,
? “admin”:true
? }
然后将其进行base64转码,得到JWT的第二部分
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
第三部分
signature
JWT的第三部分是一个签证信息,这个签证信息由三个部分组成:
?
· header (base64后的)
· payload (base64后的)
· secret
这个部分需要base64转码后的header和base64转码后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分。
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
JWT搭建
引入JWT依赖,由于是基于Java,所以需要的是java-jwt
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.2</version>
</dependency>
创建生成token的方法
public static String token (Integer id, String account){
String token = "";
try {
Date expireDate = new Date(new Date().getTime() + 10*1000);
Algorithm algorithm = Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE");
Map<String,Object> header = new HashMap<>();
header.put("typ","JWT");
header.put("alg","HS256");
token = JWT.create()
.withHeader(header)
.withClaim("id",id)
.withClaim("account",account)
.withExpiresAt(expireDate)
.sign(algorithm);
}catch (Exception e){
e.printStackTrace();
return null;
}
return token;
}
验证token是否有效
public static boolean verify(String token){
try {
Algorithm algorithm = Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE");
JWTVerifier verifier = JWT.require(algorithm).build();
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (Exception e) {
return false;
}
}
获得token 中playload部分数据
public static DecodedJWT getTokenInfo(String token){
return JWT.require(Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE")).build().verify(token);
}
用户登录成功后将用户id和账号存储到token中返回给客户端,之后客户端每次请求将token发送到服务器端验证, 在服务器中进行验证.
|