JWT的简单说明(含案例代码)

参考文章 : https://www.bilibili.com/video/BV1i54y1m7cP?p=1
看了b站up 主编程不良人 的JWT的视频后做的笔记,若想看原视频,请点击上面的参考文章


1.什么是JWT

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


通俗的说:
   JWT的全称是JSON Web Token,它是开源的,通过json的形式作为web应用中的令牌,可以安全的以json的形式传输数据。在传输过程中,可以完成数据的加密与签名等。


2.JWT能做什么

2.1.授权

  当访问的页面需要令牌时,若前端发送请求时没有携带令牌,或者令牌信息被篡改了,后端系统都不能通过验证令牌,所以就不会转发到访问的页面。比如说需要用户登录才能访问的页面,就需要携带令牌。


2.2.信息交换

  当系统A与系统B需要数据交换时,就可以用JWT来进行信息交换,以保证数据的安全,防止被篡改。因为系统每次都会检验令牌,校验不通过,系统就不使用该信息。


3. 为什么是JWT

3.1.传统的session认证

  我们知道http协议是无状态的,即当链接建立完成后,就会断开,当需要记录一些状态时(比如登录状态),就会出现问题,因为是无状态的,他不能长期存储一些信息。因此当客户端需要访问一些需要登录成功后才能访问的页面,服务器就不能知道用户是否登录了,因此就出现了session机制。
  有了session后,当我们登录后,服务器就会生成一个session,并保存到服务器内存中,然后再以cookie的形式将这个session发送给客户端,cookie的key是sessionid,value就是session的值,这样客户端就有了一个状态了,在之后客户端每次发送请求的时候,就可以在请求头的cookie中携带该session的信息以访问有保护的页面。

JWT的简单说明(含案例代码)_第1张图片

缺点:

  1. 因为session是保存在内存中的,当用户数量一多了之后,就会耗费服务器极大的资源
  2. 因为session是记录在一台服务器机上面的,当需要做分布式的时候,还需要完成session的共享,增大系统复杂度
  3. 因为是基于cookie进行用户识别的,如果cookie被截获,用户就很容易受到跨域请求伪造攻击,很不安全

3.2.JWT认证

JWT的简单说明(含案例代码)_第2张图片
认证流程:

  1. 用户输入用户名、密码登录,后端系统认证通过后会生成一个JWT,然后将这个令牌响应给客户端,让其保存到本地
  2. 客户端需要请求被保护的页面时,可以携带该令牌发送请求,后端系统会进行校验,若校验通过,放行资源,响应数据;若校验失败,则会返回错误信息,让用户进行登录

优点:

  1. JWT会进行加密处理后保存在客户端,因此是安全的
  2. 不需要在服务器保存会话信息,使用与分布式系统

4.JWT的结构

4.1. 组成

  JWT是由三段结构组成的,分别是标头(Header)、有效载荷(Payload)、签名(Signature)。这三段结构的json格式,然后再加密,就会得到JWT,因此JWT的格式如下:xxxx.yyyy.zzzz


4.2.Header

  标头由两部分组成:令牌的类型(默认为JWT) 和 JWT加密所使用的算法(如HMAC、SHA256、RSA),然后再使用 Base64 编码,构成JWT的第一部分。格式如下:

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

4.3.Payload

  有效负载是存放用户数据的声明,然后再使用 Base64 编码,构成JWT的第二部分。因此,千万能存放用户的敏感信息,因为别人是能解码看到你的敏感信息。格式如下:

{
     
	"id":"123",
	"name":"Xavier",
	"status":"yes"
}

4.4. Signature

  签名是使用前面两个json信息的 Base64 编码,再加一个盐值,最后再使用Header中指定的算法进行加密。


签名目的:
  防止信息被篡改。若有人对头部和负载的内容解码后再进行修改,再进行编码,最后再加上之前的签名组成新的JWT的话,那么服务器是无法识别该JWT的,因为篡改后的头部和负载的新签名与原来的签名是绝对不可能一样的。若对新头部和负载内容进行签名,在不知道服务器的 密钥(盐值)的情况下,是绝对得不服务器到能验证通过的值。


最终效果:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
.eyJ1X2lkIjoxMjMsImV4cCI6MTYyMDAyNDY3OCwidXNlcm5hbWUiOiJYYXZpZXIifQ
.4i3di0tXbRgRLpPIU9GRk3vBQf-13_yDZzxJl8O6CKQ

5.JWT使用

依赖:

<dependency>
    <groupId>com.auth0groupId>
    <artifactId>java-jwtartifactId>
    <version>3.15.0version>
dependency>

简单使用:

public class JWTTest {
     
    private String sing = "asd@!#987@#!#";          //盐值

    /**
     * 生成JWT
     */
    @Test
    public void contextLoads() {
     
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.DATE, 7);
        String token = JWT.create()
                .withClaim("u_id", 123)     //payload
                .withClaim("username", "Xavier")
                .withExpiresAt(instance.getTime())      //超时时间
                .sign(Algorithm.HMAC256(sing));         //签名(加密)
        System.out.println(token);
    }

    /**
     * 验证JWT,并获取其信息
     */
    @Test
    public void verify(){
     
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(sing)).build();
        DecodedJWT verify = jwtVerifier.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1X2lkIjoxMjMsImV4cCI6MTYyMDYzMDA2NCwidXNlcm5hbWUiOiJYYXZpZXIifQ.zTIeb7yJb1cKk1o7qCRiozcPafOdE7oln7cuJQZHcMA");
        Integer u_id = verify.getClaim("u_id").asInt();
        String username = verify.getClaim("username").asString();
        System.out.println(u_id);
        System.out.println(username);
    }
}

异常类型:

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

JWT验证流程:

  1. 验证算法
  2. 验证签名
  3. 对JWT解密
  4. 验证过期时间或payload

6.代码实战

GitHub代码地址:https://github.com/Xavier-777/jwt

你可能感兴趣的:(java,jwt)