JWT 结合springboot

用JWT生成token令牌,代替以前的session

以前我们完成登陆验证后,会将user信息放入session中

现在,在完成登陆验证后我们new一个map,然后将想存储的用户信息以key value的形式存储在map中(这个map也就是下面getToken方法中需要传入的参数),通过JWT.getToken(token)的到生成的token令牌

这样一来 我们之后就可以在发请求受保护的接口的时候在header中带上这个token(header中自动会有这个token) 然后用拦截器进行验证。

如果想获取token中的信息,可以在controller的参数中加上request,通过request.getHeader.get("token")拿到token... 具体流程见下面代码

maven依赖


<dependency>

  <groupId>com.auth0</groupId>

  <artifactId>java-jwt</artifactId>

  <version>3.10.3</version>

</dependency>

JWT工具类


/**

* 将JWT封装成工具类

*/

public class JWTUtils {

    // 设置sign(密钥)

    public static final String SIGN = "qweasd";

    /**

    * 生成token 形式为:header.payload.sign

    */

    public static String getToken(Map<String, String> map) {

        // 过期时间为七天

        Calendar instance = Calendar.getInstance();

        instance.add(Calendar.DATE, 7);

        // 创建JWT builder

        JWTCreator.Builder builder = JWT.create();

        // 存入信息payload中信息(也就是map中的信息)

        map.forEach((k, v) -> builder.withClaim(k, v));

        // 存入过期时间和密钥

        String token = builder.withExpiresAt(instance.getTime())

                .sign(Algorithm.HMAC256(SIGN));

        return token;

    }

    /**

    * 验证token 如果正确则返回token信息

    */

    public static DecodedJWT verify(String token) {

        // 如果token不对会直接抛出异常

        return JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);

    }

}

JWT拦截器


/**

* 避免每次都手动穿参数,我们直接写一个拦截器

*/

public class JWTInterceptor implements HandlerInterceptor {

    @Override

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        Map<String, Object> map = new HashMap<>();//实际业务中应该是Result实体类

        //从请求头中获取令牌

        String token = request.getHeader("token");

        try {

            JWTUtils.verify(token);//验证令牌

            return true;//放行请求

        } catch (SignatureVerificationException e) {

            e.printStackTrace();

            map.put("msg","无效签名!");

        }catch (TokenExpiredException e){

            e.printStackTrace();

            map.put("msg","token过期!");

        }catch (AlgorithmMismatchException e){

            e.printStackTrace();

            map.put("msg","token算法不一致!");

        }catch (Exception e){

            e.printStackTrace();

            map.put("msg","token无效!!");

        }

        map.put("state",false);//设置状态为验证失败

        //前后端分离需要返回信息是json格式的 但是不在Controller中,无法自动将map转为为json

        // 所以使用jackson手动转换

        String json = new ObjectMapper().writeValueAsString(map);

        response.setContentType("application/json;charset=UTF-8");

        response.getWriter().println(json);

        return false;

    }

}

拦截器配置


@Configuration

public class InterceptorConfig implements WebMvcConfigurer {

    @Override

    public void addInterceptors(InterceptorRegistry registry) {

        registry.addInterceptor(new JWTInterceptor())

                .addPathPatterns("/**")        //需要token验证的接口 一般是全部接口

                .excludePathPatterns("/user/**");  //用户接口都需要放行,因为登陆和注册是还没有token,如果此时验证token则肯定不会成功

    }

}

Controller层


@RestController

@Slf4j

public class UserController {

    @Autowired

    private UserService userService;

    /**

    * 生成token 返回给前段 自动存储在header中

    */

    @GetMapping("/user/login")

    public Map<String,Object> login(User user){

        log.info("用户名: [{}]",user.getName());

        log.info("密码: [{}]",user.getPassword());

        Map<String, Object> map = new HashMap<>(); // 实际业务中会使用一个Result实体类

        try{

            User userDB = userService.login(user);

            Map<String,String> payload =  new HashMap<>(); //存储用户信息用于生成token

            payload.put("id",userDB.getId());

            payload.put("name",userDB.getName());

            String token = JWTUtils.getToken(payload); // 生成JWT的令牌

            map.put("state",true);

            map.put("msg","认证成功");

            map.put("token",token);//响应token

        }catch (Exception e){

            map.put("state",false);

            map.put("msg",e.getMessage());

        }

        return map;

    }

    /**

    * 业务需要使用token中的用户信息是,通过request参数获得token

    */

    @PostMapping("/user/test")

    public Map<String,Object> test(HttpServletRequest request){

        Map<String, Object> map = new HashMap<>(); // 实际业务中会使用Result实体类

        /* 自己的业务逻辑 */

        String token = request.getHeader("token"); // 获取token

        // 验证token 必然是成功的,不然是无法进入这个路由的,这步的主要目的是获取DecodedJWT对象

      // 这步完全可以替换成 DecodedJWT verify = JWTUtils.decode(token);

        DecodedJWT verify = JWTUtils.verify(token);

        log.info("用户id: [{}]",verify.getClaim("id").asString()); // 通过getClaim获取想要的信息

        log.info("用户name: [{}]",verify.getClaim("name").asString());

        map.put("state",true);

        map.put("msg","请求成功!");

        return map;

    }

}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。