JWT整合SpringBoot

在整合SpringBoot之前,我们先封装好一个JWT的工具类,方便调用:

  1. public class JWTUtils {
  2. private static String TOKEN = "token!Q@W3e4r";
  3. /**
  4. * 生成token
  5. * @param map //传入payload
  6. * @return 返回token
  7. */
  8. public static String getToken(Map<String,String> map){
  9. JWTCreator.Builder builder = JWT.create();
  10. map.forEach((k,v)->{
  11. builder.withClaim(k,v);
  12. });
  13. Calendar instance = Calendar.getInstance();
  14. instance.add(Calendar.SECOND,7);
  15. builder.withExpiresAt(instance.getTime());
  16. return builder.sign(Algorithm.HMAC256(TOKEN)).toString();
  17. }
  18. /**
  19. * 验证token
  20. * @param token
  21. * @return
  22. */
  23. public static void verify(String token){
  24. JWT.require(Algorithm.HMAC256(TOKEN)).build().verify(token);
  25. }
  26. /**
  27. * 获取token中payload
  28. * @param token
  29. * @return
  30. */
  31. public static DecodedJWT getToken(String token){
  32. return JWT.require(Algorithm.HMAC256(TOKEN)).build().verify(token);
  33. }
  34. }

整合SpringBoot

导入依赖:

  1. <!--引入jwt-->
  2. <dependency>
  3. <groupId>com.auth0</groupId>
  4. <artifactId>java-jwt</artifactId>
  5. <version>3.4.0</version>
  6. </dependency>
  7. <!--引入mybatis-->
  8. <dependency>
  9. <groupId>org.mybatis.spring.boot</groupId>
  10. <artifactId>mybatis-spring-boot-starter</artifactId>
  11. <version>2.1.3</version>
  12. </dependency>
  13. <!--引入lombok-->
  14. <dependency>
  15. <groupId>org.projectlombok</groupId>
  16. <artifactId>lombok</artifactId>
  17. <version>1.18.12</version>
  18. </dependency>
  19. <!--引入druid-->
  20. <dependency>
  21. <groupId>com.alibaba</groupId>
  22. <artifactId>druid</artifactId>
  23. <version>1.1.19</version>
  24. </dependency>
  25. <!--引入mysql-->
  26. <dependency>
  27. <groupId>mysql</groupId>
  28. <artifactId>mysql-connector-java</artifactId>
  29. <version>5.1.38</version>
  30. </dependency>

编写配置文件:

  1. server.port=8989
  2. spring.application.name=jwt
  3. spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
  4. spring.datasource.driver-class-name=com.mysql.jdbc.Driver
  5. spring.datasource.url=jdbc:mysql://localhost:3306/jwt?characterEncoding=UTF-8
  6. spring.datasource.username=root
  7. spring.datasource.password=root
  8. mybatis.type-aliases-package=com.zym.pojo
  9. mybatis.mapper-locations=classpath:com.zym.mapper.*.xml
  10. logging.level.com.baizhi.dao=debug

数据库:

  1. DROP TABLE IF EXISTS `user`;
  2. CREATE TABLE `user` (
  3. `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  4. `name` varchar(80) DEFAULT NULL COMMENT '用户名',
  5. `password` varchar(40) DEFAULT NULL COMMENT '用户密码',
  6. PRIMARY KEY (`id`)
  7. ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

User:

  1. @Data
  2. @Accessors(chain=true)
  3. public class User {
  4. private String id;
  5. private String name;
  6. private String password;
  7. }

UserMapper与UserMapper.xml

  1. @Mapper
  2. public interface UserDAO {
  3. User login(User user);
  4. }
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.zym.mapper.UserMapper">
  6. <select id="login" resultType="com.zym.springboot_jwt.pojo.User">
  7. select * from User where name = #{name} and password = #{password};
  8. </select>
  9. </mapper>

UserService:

  1. public interface UserService {
  2. User login(User user);//登录接口
  3. }

UserServiceImpl:

  1. @Service
  2. @Transactional
  3. public class UserServiceImpl implements UserService {
  4. @Autowired
  5. private UserDAO userDAO;
  6. @Override
  7. @Transactional(propagation = Propagation.SUPPORTS)
  8. public User login(User user) {
  9. User userDB = userDAO.login(user);
  10. if(userDB!=null){
  11. return userDB;
  12. }
  13. throw new RuntimeException("登录失败~~");
  14. }
  15. }

UserController:

  1. @RestController
  2. @Slf4j
  3. public class UserController {
  4. @Autowired
  5. private UserService userService;
  6. @GetMapping("/user/login")
  7. public Map<String,Object> login(User user) {
  8. Map<String,Object> result = new HashMap<>();
  9. log.info("用户名: [{}]", user.getName());
  10. log.info("密码: [{}]", user.getPassword());
  11. try {
  12. User userDB = userService.login(user);
  13. Map<String, String> map = new HashMap<>();//用来存放payload
  14. map.put("id",userDB.getId());
  15. map.put("username", userDB.getName());
  16. String token = JWTUtils.getToken(map);
  17. result.put("state",true);
  18. result.put("msg","登录成功!!!");
  19. result.put("token",token); //成功返回token信息
  20. } catch (Exception e) {
  21. e.printStackTrace();
  22. result.put("state","false");
  23. result.put("msg",e.getMessage());
  24. }
  25. return result;
  26. }
  27. }

测试一下:
1.png
2.png
再测试一下验证Token的接口:

  1. @PostMapping("/user/test")
  2. public Map<String, Object> test(String token){
  3. Map<String,Object> map = new HashMap<>();
  4. log.info("当前Token为[{}]",token);
  5. try{
  6. DecodedJWT decodedJWT = JWTUtils.verify(token);//验证令牌
  7. map.put("state",true);
  8. map.put("msg","请求成功");
  9. return map;
  10. }catch (SignatureVerificationException e){
  11. e.printStackTrace();
  12. map.put("msg","无效签名");
  13. }catch (TokenExpiredException e){
  14. e.printStackTrace();
  15. map.put("msg","token过期");
  16. }catch (AlgorithmMismatchException e){
  17. e.printStackTrace();
  18. map.put("msg","算法不一致");
  19. }catch (Exception e){
  20. e.printStackTrace();
  21. map.put("msg","token无效");
  22. }
  23. map.put("state",false);
  24. return map;
  25. }

发送正确的token:
3.png
发送错误或者不发生token:
4.png
5.png
但是这样很麻烦,明天我们把验证的过程放到拦截器里,实现真实业务场景常用的样子