JWT,springboot整合JWT完成token的验证,token的使用,token做接口拦截

首先,介绍一下什么是JWT

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).定义了一种简洁的,自包含的方法用于通信双方之间以JSON对象的形式安全的传递信息。因为数字签名的存在,这些信息是可信的,JWT可以使用HMAC算法或者是RSA的公私秘钥对进行签名

JWT请求流程

1. 用户使用账号密码发出post请求;

2. 服务器使用私钥创建一个jwt;

3. 服务器返回这个jwt给浏览器;

4. 浏览器将该jwt串在请求头中像服务器发送请求;

5. 服务器验证该jwt;

6. 返回响应的资源给浏览器。

JWT标准的Token有三个部分组成,分别是

header:header 部分主要是两部分内容,一个是 Token 的类型,另一个是使用的算法,比如下面类型就是 JWT,使用的算法是 HS256,就是SHA-256,和md5一样是不可逆的散列算法。
payload:Payload 里面是 Token 的具体内容
signature:签名,在服务器端,用签名做token校验

springboot整合JWT

引入需要的依赖

        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.10.3</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
            <version>5.1.32</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.73</version>
        </dependency>

 JWT 工具类


/**
 * @author [email protected]
 * @date 2020/11/8 12:40
 */
public class JWTUtils {
    
    //签名 自己项目中的签名
    private static final String SIGN = "token!@19weawe2r24@#$@%!wewa98du";

    /**
     * 生成token
     *
     * @param claim 传入的payload
     * @return
     */
    public static String getToken(Map<String, String> claim) {
        JWTCreator.Builder builder = JWT.create();
        /* 
         * 1、header 用默认的就可
         * 2、设置payload .withClaim
         * 3、设置签名 .sign
         */
        claim.forEach((key, value) -> {
            builder.withClaim(key, value); //设置payload
        });
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.DAY_OF_MONTH, 7);
        builder.withExpiresAt(instance.getTime()); //设置token过期时间
        return builder.sign(Algorithm.HMAC256(SIGN));
    }

    /**
     *  校验令牌
     *
     * @param token
     */
    public static DecodedJWT verifyToken(String token) {
        return JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);
    }
}

使用拦截器拦截处理token

/**
 * @author [email protected]
 * @date 2020/11/8 13:26
 */
public class JWTInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("token");
        HashMap<String, Object> map = new HashMap<>();
        try {
            JWTUtils.verifyToken(token);
            return true;
        } catch (SignatureVerificationException e) {

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

            e.printStackTrace();
            map.put("msg","无效的签名");
        }catch (TokenExpiredException e){
            e.printStackTrace();
            map.put("msg","该令牌已过期");
        }catch (AlgorithmMismatchException e){
            e.printStackTrace();
            map.put("msg","算法不匹配");
        }catch (Exception e){
            e.printStackTrace();
            map.put("msg","token无效!");
        }
        map.put("status",false);
        String errorMsg = JSONObject.toJSONString(map);
        response.setContentType("application/json; charset=UTF-8");
        PrintWriter writer = response.getWriter();
        writer.print(errorMsg);
        writer.close();
        return false;
    }
}

 开启拦截器

/**
 * <p>
 *  
 * </p>
 *
 * @author [email protected]
 * @date 2020/11/9 9:46
 */
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(jwtInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/user/login");
    }

    @Bean
    public JWTInterceptor jwtInterceptor(){
        return new JWTInterceptor();
    }
}

 用户登录认证授权token信息

    /**
     * 认证
     * @param user
     * @param request
     * @return
     */
    @PostMapping("/login")
    public Map<String, Object> login(User user, HttpServletRequest request) {
        HashMap<String, Object> map = new HashMap<>();
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("username", user.getUsername());
        wrapper.eq("password", user.getPassword());
        try {
            User currUser = userMapper.selectOne(wrapper);
            HashMap<String, String> claim = new HashMap<>();
            claim.put("id",currUser.getId());
            claim.put("username",currUser.getUsername());
            String token = JWTUtils.getToken(claim);
            map.put("status",true);
            map.put("msg","认证成功");
            map.put("token",token);
            return map;
        } catch (Exception e) {
            map.put("status",false);
            map.put("msg","认证失败");
            return map;
        }
    }

 最后写一个接口测试一下

    /**
     * 模拟请求的接口
     * @return
     */
    @GetMapping
    public String get(){
        return "成功请求";
    }

当不携带token访问该接口时

 

认证获取token

携带token 访问测试接口

请求成功!!!

使用ajax携带token

$.ajax({
    headers: {
        "token":token
    },
    type: "get",
    url: "/test/getMessage",
    contentType: "application/x-www-form-urlencoded",
})

猜你喜欢

转载自blog.csdn.net/weixin_44912855/article/details/109545821