【业务场景实战】JWT实现用户登录

在我们平时登录注册的过程中,我们的信息都会由浏览器发送给后端进行处理,然后再插入到数据库中,下次我们进行登录的时候,只需要输入用户名和密码就可以登录成功进入网站进行操作了。

但个人信息暴露在大众面前这是极其不安全的,对于我们的隐私,我们并不希望被别人知道。所以我们在登录的时候,浏览器中进行传递的数据有些是会脱敏、有些是需要进行加密之后才能进行传递的。

一、JWT简介

JWT(全称JSON WEB Token):是实现token的机制。,是一种用于安全传输信息的紧凑、URL安全的令牌格式,通常用于身份验证和授权

1、JWT的组成

JWT由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。

头部:包含令牌的元数据,例如使用的加密算法和令牌类型等。

载荷:包含声明(Claims),即要传递的信息,如用户ID、角色、过期时间等。

签名:用于验证消息在传递过程中是否被篡改,它是通过将头部和载荷进行Base64编码后,使用指定的签名算法和一个密钥生成的。

Token是用于身份验证和授权的令牌,保证只有经身份验证和授权的用户才能访问特定的资源。可提高安全性。

2、JWT的校验流程

用户使用用户名和密码进行登录,服务器验证用户信息是否正确。

服务器生成一个JWT,将用户信息、权限等信息写入载荷中,并使用密钥对头部和载荷进行签名。

服务器将生成的JWT返回给客户端,客户端将其存储在本地。客户端在后续请求中,将JWT作为请求头部或请求参数传递给服务器。

服务器收到请求后,验证JWT的签名是否正确,如果正确则解析出用户信息、权限等信息,进行后续操作。

二、代码实现

1、引入依赖



    com.auth0
    java-jwt
    3.19.0


    cn.hutool
    hutool-all
    5.7.4

2、JWT签名工具类

import cn.hutool.core.date.DateUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.yupi.model.domain.User2;
import com.yupi.service.User2Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
@Component
public class JwtUtil {

    @Autowired
    User2Service user2Service;

    /**
     * 创建jwt
     * @param user
     * @return
     */
    public String createToken(User2 user){
        String sign = JWT.create()
            // 设置载荷
            .withAudience(user.getId().toString())
            // 设置签名过期的时间:24小时后
            .withExpiresAt(DateUtil.offsetHour(new Date(), 24)) 
            // 设置签名密钥 Signature
            .sign(Algorithm.HMAC256(user.getUserPassword()));
        return sign;
    }

    /**
     * 校验Token,返回用户信息
     * @param token
     * @return
     */
    public User2 verify(String token){
        DecodedJWT decode = JWT.decode(token);
        String userId = decode.getAudience().get(0);
        User2 user = user2Service.getById(userId);
        //获取校验器
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getUserPassword())).build();
        jwtVerifier.verify(token);
        return user;
    }
}

这段生成签名的方法形式和上篇API签名认证的签名生成方式差不多

生成签名方法:

  • 首先使用JWT.create()创建一个新的JWT对象。
  • 通过调用withAudience()方法来设置载荷,将用户的ID转换为字符串并作为载荷传递给该方法。
  • 使用withExpiresAt()方法设置签名的过期时间,这里设置为当前时间加上24小时。
  • 设置签名密钥:使用sign()方法对JWT进行签名,签名算法使用的是HMAC-SHA256算法,密钥是用户的密码。
  • 最终,生成的JWT令牌被存储在变量sign中,并返回给调用者。

在这里同样密码也是不在浏览器中进行传递的,是从数据库中获取的

校验签名方法:这个方法的作用是验证传入的JWT令牌是否有效,并返回对应的用户信息。

  • 使用JWT.decode(token)方法对传入的令牌进行解码,得到一个DecodedJWT对象。
  • 通过调用decode.getAudience()方法获取令牌中的用户ID
  • 根据用户ID从数据库中获取对应的用户信息
  • 通过从数据库中获取到的用户密码(也就是我们这里的密钥) 将创建的HMAC256算法实例传递给JWT.require()方法,构建一个JWT验证器。这个验证器可以用来验证JWT令牌的有效性。
  • 使用jwtVerifier.verify(token)方法验证令牌是否有效。如果令牌有效,则该方法不会抛出异常;否则,会抛出异常。

这里和我们上一篇的API签名认证稍有不同,API签名认证里面是我们通过获取到的密钥再次生成签名,然后拿两个签名去比较。而这里,我们是通过用户密码(密钥)去创建了一个校验器,然后去验证JWT。

通俗一点来讲,我们之前是使用钥匙配好了一把锁,然后我们是去配另一把锁,如果匹配上,那这两把锁就是相同的。现在我们是拿另一把钥匙去匹配同一把锁,如果匹配上,那说明这把钥匙和之前那把就是一样的。

总结一下步骤:

  • 解码JWT: 首先解码JWT以提取其中的信息。
  • 获取用户ID: 从解码后的JWT中提取用户ID。
  • 获取用户信息: 根据用户ID获取用户信息。
  • 创建校验器: 使用用户的密码作为密钥创建一个JWT校验器。
  • 验证JWT: 使用校验器验证JWT的有效性。
  • 返回用户信息: 如果验证通过,返回用户信息。

3、签名请求

输入用户名和密码发起请求,然后根据用户名和密码和数据库中进行比对实现登录,

获取到user对象,然后使用jwtUtil工具类中的创建签名方法来生成token

登录的逻辑这里就不写了,就是去数据库查询

@GetMapping("/jwt/login")
public String jwtLogin(UserLoginRequest userLoginRequest, HttpServletRequest request){
    String userAccount = userLoginRequest.getUserAccount();
    String userPassword = userLoginRequest.getUserPassword();

    User2 user = userService.userLogin(userAccount, userPassword, request);

    String token = jwtUtil.createToken(user);
    return token;
}

请求成功

【业务场景实战】JWT实现用户登录_第1张图片

4、签名验证请求

从request的请求头中获取token,然后通过签名工具类获取到用户信息返回

@GetMapping("/jwt/test")
    public User jwtTest(HttpServletRequest request) {
        String token = request.getHeader("Authorization");
        User user = jwtUtil.verify(token);
        return user;
    }

【业务场景实战】JWT实现用户登录_第2张图片

JWT登录验证成功

今天我的分享到此结束,欢迎大家点赞、评论、关注!!!

你可能感兴趣的:(java)