JWT入门知识总结

一、什么是JWT

在这里插入图片描述
官网地址: https://jwt.io/introduction/

JSON Web Token(JWT)是一个开放标准(rfc7519),它定义了一种紧凑的、自包含的方式,用于在各方之间以JSON对象安全地传输信息。此信息可以验证和信任,因为它是数字签名的。jwt可以使用秘密(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。

JWT简称JSON Web Token,也就是通过JSON形式作为Web应用中的令牌,用于在各方之间安全地将信息作为JSON对象传输。在数据传输过程中还可以完成数据加密、签名等相关处理。

二、JWT能做什么?

2.1 授权

这是使用JWT的最常见方案。一旦用户登录,每个后续请求将
包括JWT,从而允允许的路由,服务和资源。单点登录是当今
广泛使用JWT的一项功能,因为它的开销很小并且可以在不同
的域中轻松使用。

2.2信息交换

JSON Web Token是在各方之间安全地传输信息的好方法。因为
可以对JWT进行签名(例如,使用公钥/私钥对),所以您可
以确保发件人是他们所说的人。此外,由于签名是使用标头和有
效负载计算的,因此您还可以验证内容是否遭到篡改。

注意:jwt跟session不一样,jwt存储在客户端,session存储在服务器端,服务器断电后session就没了,而jwt因为存储在客户端,所以就不会被影响,只要jwt不过期,就可以继续使用。

三、为什么是JWT?

3.1 基于传统的Session认证

3.1.1 认证方式

我们知道,http协议本身是一种无状态的协议,而这
就意味着如果用户向我们的应用提供了用户名和密码来进行用
户认证,那么下一次请求时,用户还要再一次进行用户认证
才行,因为根据http协议,我们并不能知道是哪个用户发出
的请求,所以为了让我们的应用能识别是哪个用户发出的请求,我
们只能在服务器存储一份用户登录的信息,这份登录信息会在响
应时传递给浏览器,告诉其保存为cookie,以便下次请求时发送
给我们的应用,这样我们的应用就能识别请求来自哪个用
户了,这就是传统的基于session认证。

3.1.2 认证流程

请添加图片描述

3.1.3暴露问题

1.每个用户经过我们的应用认证之后,我们的应用都要在服务端做
一次记录,以方便用户下次请求的鉴别,通常而言session都是保
存在内存中,而随着认证用户的增多,服务端的开销会明显增大

2.用户认证之后,服务端做认证记录,如果认证的记录被保存在
内存中的话,这意味着用户下次请求还必须要请求在这台服务
器上,这样才能拿到授权的资源,这样在分布式的应用上,相应
的限制了负载均衡器的能力。这也意味着限制了应用的扩展能力。

3.因为是基于cookie来进行用户识别的, cookie如果被截获,用户
就会很容易受到跨站请求伪造的攻击。

4.在前后端分离系统中就更加痛苦:如下图所示
也就是说前后端分离在应用解耦后增加了部署的复杂性。通常用户
一次请求就要转发多次。如果用session 每次携带sessionid 到服务
器,服务器还要查询用户信息。同时如果用户很多。这些信息存储
在服务器内存中,给服务器增加负担。还有就是CSRF(跨站伪造
请求攻 击)攻击,session是基于cookie进行用户识别的, cookie如
果被截获,用户就会很容易受到跨站请求伪造的攻击。还有就是
sessionid就是一个特征值,表达的信息不够丰富。不容易扩展。
而且如果你后端应用是多节点部署。那么就需要实现session共
享机制。不方便集群应用。

请添加图片描述

3.2 基于JWT认证

请添加图片描述

3.2.1 认证流程

首先,前端通过Web表单将自己的用户名和密码发送到后端的接口。
这一过程一般是一个HTTP POST请求。建议的方式是通过SSL加
密的传输(https协议),从而避免敏感信息被嗅探。

后端核对用户名和密码成功后,将用户的id等其他信息作为
JWT Payload(负载),将其与头部分别进行Base64编码拼接后
签名,形成一个JWT(Token)。形成的JWT就是一个形同lll.zzz.xxx
的字符串。 token head.payload.singurater

后端将JWT字符串作为登录成功的返回结果返回给前端。前端可
以将返回的结果保存在localStorage或sessionStorage上,退出登录
时前端删除保存的JWT即可。

前端在每次请求时将JWT放入HTTP Header中的Authorization位。
(解决XSS和XSRF问题) HEADER

后端检查是否存在,如存在验证JWT的有效性。例如,检查签名
是否正确;检查Token是否过期;检查Token的接收方是否是自己(可选)。

验证通过后后端使用JWT中包含的用户信息进行其他逻辑操作,
返回相应结果。

3.2.2 JWT优势

简洁(Compact): 可以通过URL,POST参数或者在HTTP header发送,
因为数据量小,传输速度也很快

自包含(Self-contained):负载中包含了所有用户所需要的信息,
避免了多次查询数据库

因为Token是以JSON加密的形式保存在客户端的,所以JWT是跨语
言的,原则上任何web形式都支持。

不需要在服务端保存会话信息,特别适用于分布式微服务。

四、JWT的结构是什么?

token string ====> header.payload.singnature token

4.1 令牌组成

  • 1.标头(Header)
  • 2.有效载荷(Payload)
  • 3.签名(Signature)
  • 因此,JWT通常如下所示:xxxxx.yyyyy.zzzzz Header.Payload.Signature

4.2 Header

  • 标头通常由两部分组成:令牌的类型(即JWT)和所使用的签名算法,例如HMAC SHA256或RSA。它会使用 Base64 编码组成 JWT 结构的第一部分。

  • 注意:Base64是一种编码,也就是说,它是可以被翻译回原来的样子来的。它并不是一种加密过程。

{
  "alg": "HS256",
  "typ": "JWT"
}

4.3 Payload

  • 令牌的第二部分是有效负载,其中包含声明。声明是有关实体
  • (通常是用户)和其他数据的声明。同样的,它会使用
    Base64 编码组成 JWT 结构的第二部分
{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

4.4 Signature

  • 前面两部分都是使用 Base64 进行编码的,即前端可以解开知
    道里面的信息。Signature 需要使用编码后的 header 和 payload
    以及我们提供的一个密钥,然后使用 header 中指定的签名算法
    (HS256)进行签名。签名的作用是保证 JWT 没有被篡改过
  • 如:
    HMACSHA256(base64UrlEncode(header) + “.” + base64UrlEncode(payload),secret);

4.5 签名目的

  • 最后一步签名的过程,实际上是对头部以及负载内容进行签名,
    防止内容被窜改。如果有人对头部以及负载的内容解码之后进行修
    改,再进行编码,最后加上之前的签名组合形成新的JWT的话,
    那么服务器端会判断出新的头部和负载形成的签名和JWT附带上
    的签名是不一样的。如果要对新的头部和负载进行签名,在不知
    道服务器加密时用的密钥的话,得出来的签名也是不一样的。

4.6 信息安全问题

  • 在这里大家一定会问一个问题:Base64是一种编码,
    是可逆的,那么我的信息不就被暴露了吗?

  • 是的。所以,在JWT中,不应该在负载里面加入任何敏感的
    数据。在上面的例子中,我们传输的是用户的User ID。这个值
    实际上不是什么敏 感内容,一般情况下被知道也是安全的。但
    是像密码这样的内容就不能被放在JWT中了。如果将用户的密
    码放在了JWT中,那么怀有恶意的第 三方通过Base64解码就能
    很快地知道你的密码了。因此JWT适合用于向Web应用传递一些
    非敏感信息。JWT还经常用于设计用户认证和授权系 统,甚至
    实现Web应用的单点登录。

请添加图片描述

五、使用JWT

5.1 引入依赖

<!--引入jwt-->
<dependency>
  <groupId>com.auth0</groupId>
  <artifactId>java-jwt</artifactId>
  <version>3.4.0</version>
</dependency>

5.2 生成Token

Calendar instance = Calendar.getInstance();
instance.add(Calendar.SECOND, 90);
//生成令牌
String token = JWT.create()
  .withClaim("username", "张三")//设置自定义用户名
  .withExpiresAt(instance.getTime())//设置过期时间
  .sign(Algorithm.HMAC256("token!Q2W#E$RW"));//设置签名 保密 复杂
//输出令牌
System.out.println(token);

5.2.1 生成结果

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOlsicGhvbmUiLCIxNDMyMzIzNDEzNCJdLCJleHAiOjE1OTU3Mzk0NDIsInVzZXJuYW1lIjoi5byg5LiJIn0.aHmE3RNqvAjFr_dvyn_sD2VJ46P7EGiS5OBMO_TI5jg

5.3 根据令牌和签名解析数据

JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("token!Q2W#E$RW")).build();
DecodedJWT decodedJWT = jwtVerifier.verify(token);
System.out.println("用户名: " + decodedJWT.getClaim("username").asString());// 存的是时候是什么类型,取得时候就是什么类型,否则取不到值。
System.out.println("过期时间: "+decodedJWT.getExpiresAt());

5.4 常见异常信息

SignatureVerificationException签名不一致异常
TokenExpiredException令牌过期异常
AlgorithmMismatchException算法不匹配异常
InvalidClaimException失效的payload异常

请添加图片描述

public class JWTUtils {
    private static String TOKEN = "token!Q@W3e4r";
    /**
     * 生成token
     * @param map  //传入payload
     * @return 返回token
     */
    public static String getToken(Map<String,String> map){
        JWTCreator.Builder builder = JWT.create();
        map.forEach((k,v)->{
            builder.withClaim(k,v);
        });
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.SECOND,7);
        builder.withExpiresAt(instance.getTime());
        return builder.sign(Algorithm.HMAC256(TOKEN));
    }
    /**
     * 验证token
     * @param token
     * @return
     */
    public static void verify(String token){
        JWT.require(Algorithm.HMAC256(TOKEN)).build().verify(token);  // 如果验证通过,则不会把报错,否则会报错
    }
    /**
     * 获取token中payload
     * @param token
     * @return
     */
    public static DecodedJWT getToken(String token){
        return JWT.require(Algorithm.HMAC256(TOKEN)).build().verify(token);
    }
}

参考链接:https://blog.csdn.net/unique_perfect/article/details/109219826

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王菜鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值