【springboot进阶】jwt在前后端分离的最佳实践方式(一)

目录

一、什么是前后端分离

二、jwt起源

三、token认证机制

四、jwt构成

头部header

载荷payload

签证 signature

五、如何应用


第一小节,我们先对一些背景和相关术语进行说明。

一、什么是前后端分离

用通俗的话讲就是:前端开发人员做页面样式的开发,后端开发人员处理功能逻辑开发,互不干扰各做各的部分,最终后端开发人员通过协商好的接口协议(一般是json格式)提供给前端开发人员数据,进行页面数据渲染。

前后端分离是目前热门的开发方式,大部分互联网都会采用前后端分离的方式开发。它的优点也很明显,相对于以往传统的单体结构系统,前后端耦合度降低,工作效率得到明显的提高。同时随着vue等一些前端技术栈越来越丰富,前后端开发的模式变得越来越流行。

二、jwt起源

在传统的单体结构系统中,一般会使用session认证,这是一种基于服务器端的认证方式,一般服务器存储一份用户登录的信息到内存,并通过前端cookie技术,使应用系统能识别请求来自哪个用户。

这样的弊端也很明显,因为服务器要对每一个认证用户都需要保存一份信息,所以服务端的开销会明显增大。其次不便于扩展,特别在分布式的架构上,为了确保用户的请求能到达同一认证服务器上,相应的限制了负载均衡器的能力。

基于以上的问题,我们一般采用token认证机制来解决。

三、token认证机制

token认证机制,它是无状态的,它不需要在服务端保存用户的认证信息。这就意味着基于token认证机制的应用系统不需要去考虑用户在哪一台服务器认证过了,这就有利于应用的扩展。

一般的token认证机制如下:

  1. 用户认证信息发送到服务器
  2. 服务器对用户认证信息进行校验
  3. 服务器校验通过后,返回用户端一个token
  4. 用户端存储token,并在每次请求时带上这个token值
  5. 服务器对请求的token值进行合法验证,如果验证通过,则允许用户访问相应资源 

四、jwt构成

jwt是由三段信息构成:第一部分为头部(header),第二部分为载荷(payload),第三部分是签证(signature)。

jwt字符串样例:

//每个小圆点间为一部分,一共是三段内容拼接而成
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiMTIzNDU2IiwidXNlcl9uYW1lIjoi5byg5LiJIiwiZXhwIjoxNjU0NTI2MDU5fQ.MCuHhUOoRkMeabCk2SlfubDAL7ZgOopn7nti5QDaEhY

头部header

jwt的头部有两部分信息:

  • 声明类型,为jwt
  • 声明加密的算法,为HMAC SHA256

样例中的头部信息

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

载荷payload

载荷就是存放有效信息的地方。这些信息包含三个部分:

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

样例中的载荷信息,定义了用户id、用户姓名、还携带了一个过期时间。

{
    "user_id": "123456",
    "user_name": "张三",
    "exp": 1654526059
}

*注意:因为密文可通过base64解密,所以载荷中不要存放敏感信息,如用户密码、身份证等。

签证 signature

jw签证信息由三部分组成:

  • header (base64)
  • payload (base64)
  • secret

这个部分是由base64加密后的header和base64加密后的payload,然后通过'.'连接组成的字符串,最后通过header中声明的加密方式进行加盐secret组合加密得出。

五、如何应用

需在项目pom.xml引入jwt依赖包

    
      com.auth0
      java-jwt
      3.19.1
    

服务器端生成jwt样例 

//密钥secret
String JWT_USER_AUTH_SECRET = "qwerasdf123";

JWTCreator.Builder builder = JWT.create();
//添加claim
builder.withClaim("user_id", "123456");
builder.withClaim("user_name", "张三");
//设置JWT令牌的过期时间为一天
Calendar instance = Calendar.getInstance();
instance.add(Calendar.SECOND, 1 * 86400);
builder.withExpiresAt(instance.getTime());
//生成JWT
String token = builder.sign(Algorithm.HMAC256(JWT_USER_AUTH_SECRET));
System.out.println(token);

前端开发调用接口时在请求头里加入Authorization,并加上Bearer标注

fetch('api/user/123456', {
  headers: {
    'Authorization': 'Bearer ' + token
  }
})

你可能感兴趣的:(springboot进阶应用,前端)