Springboot整合jwt登录验证

386 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第14天,点击查看活动详情

JWT,全程是叫做Json Web Token,定义了一种紧凑的,自包含的方式,用于在各方之间以json对象的方式安全地传输信息,该信息可用于验证身份信息。

jwt验证方式是将用户信息通过加密生成token,每次请求服务端只需要使用保存的密钥验证token的正确性,不用再保存任何session数据了,进而服务端变得无状态,容易实现拓展。

鉴权流程

使用jwt作为服务认证的原理是用户登录后,服务端会将用户信息通过jwt工具类加密处理,生成一个token,该token可以设置有效期时间,然后将token返回给用户端。用户端在接收到返回的token时可以将其保存至缓存中,以后每次请求服务端接口时都要在header中将token携带发送给服务器。服务端进行验证用户的身份、权限、有效期等信息,验证通过即放行,验证不通过就拒绝服务。

引入maven依赖

<!-- JWT -->
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.10.3</version>
</dependency>

集成jwt工具类

/**
 * 生成token
 * @return
 */
public static String genToken(String userId, String sign) {
    return JWT.create().withAudience(userId) // 将 user id 保存到 token 里面,作为载荷
            .withExpiresAt(DateUtil.offsetHour(new Date(), 2)) // 2小时后token过期
            .sign(Algorithm.HMAC256(sign)); // 以 password 作为 token 的密钥
}

/**
 * 获取当前登录的用户信息
 * @return user对象
 */
public static User getCurrentUser() {
    try {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token = request.getHeader("token");
        if (StrUtil.isNotBlank(token)) {
            String userId = JWT.decode(token).getAudience().get(0);
            return staticUserService.getById(Integer.valueOf(userId));
        }
    } catch (Exception e) {
        return null;
    }
    return null;
}

编写拦截器

@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String token = request.getHeader("token");
        // 如果不是映射到方法直接通过
        if(!(handler instanceof HandlerMethod)){
            return true;
        }
        // 执行认证
        if (StrUtil.isBlank(token)) {
            throw new ServiceException(Constants.CODE_401, "无token,请重新登录");
        }
        // 获取 token 中的 user id
        String userId;
        try {
            userId = JWT.decode(token).getAudience().get(0);
        } catch (JWTDecodeException j) {
            throw new ServiceException(Constants.CODE_401, "token验证失败,请重新登录");
        }
        // 根据token中的userid查询数据库
        User user = userService.getById(userId);
        if (user == null) {
            throw new ServiceException(Constants.CODE_401, "用户不存在,请重新登录");
        }
        // 用户密码加签验证 token
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
        try {
            jwtVerifier.verify(token); // 验证token
        } catch (JWTVerificationException e) {
            throw new ServiceException(Constants.CODE_401, "token验证失败,请重新登录");
        }
        return true;
    }`

在每次请求服务端时,都会进入拦截器来进行token验证判断,如果无token或者token验证失败将会拒绝请求,抛出异常并返回给用户端。