JWT的使用

JWT,是什么,做什么用,怎么用,为什么要用:

全称:Json Web Token

是什么:

是一个开发标准,定义了一个紧凑的,自包含的方式,

干什么用的:

用于各方之间以json对象安全地传输信息,传输中还可以对数据进行加密,签名处理。

怎么用:

一。授权,用户登录后,后续每个请求都包含JWT,从而允许用户访问该令牌允许的 路由,服务和资源,,单点登录是当今广泛使用JWT的一项功能,有开销少,可在不同域中使用的功能

二。信息交换,JSON Web令牌是在各方之间安全地传输信息的一种好方式,所以可以对JWT进行签名,但要确保发件人就是本人,此外,签名是使用标头和有效负载计算的,因此还可以验证内容是否被篡改。

为什么要用:

因为HTTP协议是无状态的,如果我们已近认证了一个用户,那么他下一次发起请求时,服务器不能识别我们,我们就必须再次认证。

为了避免这种情况的发生我们就可以使用;

Cookie+Session的方式,当用户登录成功后,我们把用户的信息保存到我们的Session中,然后把该Session以Cookie的形式保存到客户端浏览器上,此后,该用户的所有请求都会把包含Sessionld的Cookie带回给服务器,服务器获取到Sessionld,通过改Sessionld得到Session对象,这样就能获取到该用户登录时的信息了

但这种方式也有缺点:

1.每次用户认证后,服务器都要创建一个Session对象保存用户信息,用户越多,服务器保存的session也越多,服务器的内存开销也会越来越大

2.Sessionld是基于Cookie来储存的,如果Cookie被截获,用户很容易受到跨站请求伪造攻击(CSRF)

3.当我们扩展应用,数据被多个移动设备使用时,我们必须考虑跨资源共享的问题,当使用AJAX调用 从另一个域名下获取资源时,可能会出现禁止请求的问题(CORS)

4.在分布式集群系统中,我们的后端应用是多节点部署,而session是储存在节点服务器上,这个时候又要实现Session的共享机制,所以不方便集群应用。

我们还可以使用:

基于iJWT的认证方式:

  1. 前端通过web表单将自己的用户名和密码发送给后端的接口,这一过程一般就是一个HTTP POST请求.在实际开发中,我们可以通过SSL加密的传输(Https协议),从而避免敏感信息被嗅探.
  2. 后端核对用户名和密码成功之后,将用户的id等其他信息作为JWT的payload(负载),将其与头部分别进行base64编码拼接之后签名,形成一个JWT(token).形成的JWT就是一个形同:aaa.bbb.ccc的字符串.
  3. 后端服务将JWT字符串作为登录成功的返回结果返回给前端,前端可以将返回的结果保存在LocalStore或sessionStore上,退出登录时,前端删除保存的JWT即可.
  4. 前端在每次请求时,将JWT放入HTTP的请求头中的Authorization中(解决XSS和XSRF问题)
  5. 后端验证JWT的有效性,例如:检查签名是否正确,检查Token是否过期,检查Token的接收方是否是自己的(可选)
  6. 验证通过后,后端使用JWT中包含的用户信息进行其他逻辑操作,返回相应的结果.
  7. 如果验证不通过, 响应错误信息给用户.

JWT与Session的差异:

相同点是,它们都是存储用户信息;然而,Session是在服务器端的,而JWT是在客户端的。

Session方式存储用户信息的最大问题在于要占用大量服务器内存,增加服务器的开销。

而JWT方式将用户状态分散到了客户端中,可以明显减轻服务端的内存压力。

Session的状态是存储在服务器端,客户端只有session id;而Token的状态是存储在客户端。

JWT的优势:

1.简洁:可以通过URL,POST参数或Http请求头发送,因为数据量小,传输速度也快;

2.自包含:负载包含了用户所需要的数据,避免多次查询数据库

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

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

JWT的结构:

JSON Web令牌以紧凑的形式由三部分组成,这些部分由点(.)分隔,分别是:

  • 头部(header)
  • 载荷 (payload)
  • 签名(signature)

JWT通常如下所示: xxxxxx.yyyyyy.zzzzz

示例:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJVc2VySWQiOjEyMywiVXNlck5hbWUiOiJhZG1pbiJ9.Qjw1epD5P6p4Yy2yju3-fkq28PddznqRj3ESfALQy_U

头部:

由两个部分组成:

令牌类型:JWT

签名算法:(如:HMAC,SHA256或RSA)

载荷:载荷中放置了 token 的一些基本信息

用来理解token,同时还可以包含一些自定义的信息,用户信息交换。这些信息包含:

  • 标准中注册声明
  • 公共的声明
  • 私有的声明

标准中注册声明(建议不强制使用)

公共的声明

在使用 JWT 时可以额外定义的载荷。为了避免冲突,应该使用 IANA JSON Web Token Registry 中定义好的,或者给额外载荷加上类似命名空间的唯一标识。

公共的声明可以添加任何的信息,一般添加用户的相关信息或其它业务需要的必要信息,但不建议添加敏感信息,因为该部分在客户端可解密;

私有的声明

在信息交互的双方之间约定好的,既不是预定义载荷也不是公有载荷的一类载荷。这一类载荷可能会发生冲突,所以应该谨慎使用。

比如我们定义了一个payload:

{ "sub": "1234567890", "name": "John Doe", "admin": true }

然后将其base64url加密,得到jwt的一部分

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9

请注意,对于已签名的令牌,此信息尽管可以防止篡改,但任何人都可以读取。除非将其加密,否则请勿将机密信息放入JWT的有效负载或报头元素中。

JWT的总结

JWT的优点:

  • 因为json的通用性,所以JWT是可以跨语言支持的,像C#,JavaScript,NodeJS,PHP等许多语言都可以使用
  • 因为由了payload部分,所以JWT可以在自身存储一些其它业务逻辑所必要的非敏感信息
  • 便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的
  • 它不需要在服务端保存会话信息,所以它易于应用的扩展安全相关
  • 不应该在jwt的payload部分存储敏感信息,因为该部分是客户端可解密的部分
  • 保护好secret私钥。该私钥非常重要
  • 如果可以,请使用https协议

JWT的java实现

1.导入依赖

io.jsonwebtoken

jjwt

0.9.1

代码实现:

@Test

public void testCreateToken(){

Calendar instance = Calendar.getInstance();

instance.add(Calendar.SECOND,90);

JwtBuilder builder = Jwts.builder().setId("888").setSubject("zhangsan")

.setIssuedAt(new Date())//设置签发时间

.signWith(SignatureAlgorithm.HS256, "feisi")//使用HS256生成token,签名秘钥 则是feisi,唯一密钥的话可以保存在服务端。

.setExpiration(instance.getTime());//设置过期时间

System.out.println(builder.compact());

}

生成的token内容:

eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiJ6aGFuZ3NhbiIsImlhdCI6MTY5MTI0NTMzMSwiZXhwIjoxNjkxMjQ1NDIxfQ._aKLZld6rlf-Vt6xkdihFFJLpptbW4exvPBAttA2g4I

再次运行,会发现每次运行的结果是不一样的,因为我们的载荷中包含了时间

3.根据token和签名解析数据

我们刚才已经创建了token ,在web应用中这个操作是由服务端进行然后发给客户端,客户端在下次向服务端发送请求时需要携带这个token(这就好像是拿着一张门票一样),那服务端接到这个token应该解析出token中的信息(例如用户id),根据这些信息查询数据库返回相应的结果。

@Test

public void testProcessToke(){

String token ="eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiJ6aGFuZ3NhbiIsImlhdCI6MTY5MTI0NTMzMSwiZXhwIjoxNjkxMjQ1NDIxfQ._aKLZld6rlf-Vt6xkdihFFJLpptbW4exvPBAttA2g4I";

Claims claims =

Jwts.parser().setSigningKey("feisi").parseClaimsJws(token).getBody();

System.out.println("id:"+claims.getId());

System.out.println("subject:"+claims.getSubject());

System.out.println("IssuedAt:"+claims.getIssuedAt());

System.out.println("expiration:"+claims.getExpiration());

}

4.常见的异常信息:

  • ClaimJwtException:在验证JWT声明失败后抛出
  • ExpiredJwtException:表示JWT在过期后被接受,必须被拒绝
  • MalformedJwtException:当JWT未正确构造并且应该被拒绝时抛出
  • PrematureJwtException:表示JWT在被允许访问之前被接受,必须被拒绝
  • SignatureException:表示计算签名或验证JWT的现有签名失败
  • UnsupportedJwtException:在接收到与应用程序预期格式不匹配的特定格式/配置的JWT时抛出。例如,如果在应用程序需要加密签名的声明JWS时解析无符号明文JWT,则会抛出此异常
  • JJWT使用了许多其他Exception类。它们都可以在JJWT源代码中的io.jsonwebtoken包中找到。
Hertz JWT 使用通常涉及到在 API 开发中对访问控制、身份验证和授权的管理。JWT (JSON Web Token) 是一种开放标准,用于安全地传输数据作为令牌,并可以在客户端和服务端之间进行验证。当结合 Hertz 框架使用时,可以有效提升 RESTful API 的安全性。 ### Hertz 中 JWT 的应用 1. **身份验证**:通过 JWT 提供了一个自包含的身份认证机制,允许客户端一次性携带身份信息,在请求过程中不需要再次提供凭证。 2. **权限控制**:JWT 可以携带用户角色或其他授权信息,服务端可以根据这些信息做出相应的访问决策。 3. **状态无状态性**:由于 JWT 是自包含的,它消除了对会话存储的需求,使得应用程序更易于分布式部署。 4. **加密与签名**:使用哈希算法如 HMAC 或 RSA 进行签名,保证了数据的完整性和来源的可信度。 ### 实现步骤 #### 客户端生成 JWT 1. 发起一次认证请求给服务器,例如登录请求,返回包含用户名等信息的响应。 ```http POST /login HTTP/1.1 Host: example.com username=example_user&password=example_password ``` 2. 服务器验证凭据并生成 JWT,通常包括 token、过期时间等字段,并将其返回给客户端。 ```json { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c", "exp": 1682797600, // 其他信息... } ``` #### 服务端验证 JWT 1. 接收到请求,从请求头(通常是 `Authorization` 字段)提取 JWT。 ```http GET /protected-resource HTTP/1.1 Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c ``` 2. 使用相同的密钥解码 JWT,并验证其完整性及有效性。 3. 根据 JWT 中的信息进行授权处理,如检查用户角色、过期时间等。 ### 相关问题: 1. **如何确保 JWT 在传输过程中的安全性?** 使用 HTTPS 协议保护数据传输的安全,防止中间人攻击。同时,可以采用 AES 加密或其他更高级别的加密技术来进一步增强安全性。 2. **如何在 Hertz 框架中集成 JWT 验证机制?** 可以使用第三方库(如 gjwt)简化 JWT 验证的过程,或者自定义实现验证逻辑。这通常涉及拦截 HTTP 请求,读取 JWT使用预设的密钥进行解码和验证。 3. **JWT 的生命周期管理有哪些注意事项?** - 确保设置合理的过期时间,避免长时间有效性的 JWT 被滥用。 - 定期清理无效或已撤销的 JWT,减少资源消耗和潜在的风险。 - 对敏感操作如账户更改密码等,考虑使用短生命周期的刷新令牌而非原始的访问令牌。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值