> 文档中心 > SpringBoot 整合 JWT(基于jwt)

SpringBoot 整合 JWT(基于jwt)


SpringBoot 整合 JWT (基于jwt)

0、环境搭建:

  1. 新建数据库表

    SET NAMES utf8mb4;SET FOREIGN_KEY_CHECKS = 0;-- ------------------------------ Table structure for user-- ----------------------------DROP TABLE IF EXISTS `user`;CREATE TABLE `user`  (  `user_id` int(11) NOT NULL,  `user_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,  `password` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,  `real_name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,  `phone` char(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,  `email` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,  `gender` enum('0','1') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,  `create_time` datetime NULL DEFAULT NULL,  `modify_time` datetime NULL DEFAULT NULL,  `enable` tinyint(1) UNSIGNED ZEROFILL NULL DEFAULT NULL,  PRIMARY KEY (`user_id`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;-- ------------------------------ Records of user-- ----------------------------INSERT INTO `user` VALUES (1, 'root', '123456', '吴禹凡', '18358659682', '341419199@qq.xom', '0', '2021-09-20 23:20:07', NULL, 1);SET FOREIGN_KEY_CHECKS = 1;
  2. 导入依赖:

    <dependency>    <groupId>com.auth0</groupId>    <artifactId>java-jwt</artifactId>    <version>3.18.2</version></dependency><dependency>    <groupId>com.alibaba</groupId>    <artifactId>druid</artifactId>    <version>1.2.6</version></dependency><dependency>    <groupId>mysql</groupId>    <artifactId>mysql-connector-java</artifactId></dependency><dependency>    <groupId>com.baomidou</groupId>    <artifactId>mybatis-plus-boot-starter</artifactId>    <version>3.4.3.3</version></dependency><dependency>    <groupId>org.projectlombok</groupId>    <artifactId>lombok</artifactId>    <optional>true</optional></dependency>
  3. 配置 application.yml 配置文件

    server:  port: 8080spring:  datasource:    username: root    password: root    url: jdbc:mysql://localhost:3306/mybatis?useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai    driver-class-name: com.mysql.cj.jdbc.Driver    type: com.alibaba.druid.pool.DruidDataSourcelogging:  level:    root: info    cn.edu.hziee: debugmybatis-plus:  configuration:    mapUnderscoreToCamelCase: true  type-aliases-package: cn.edu.hziee.pojo  jwt:  # JWT 存储的请求头  tokenHeader: Authorization  # JWT 加密解密使用的密钥  secretKey: "!QAzxZ@12^3#asd.$01.0.."  # JWT 的过期时长(60*60*24*7)  expiration: 2235200  # 负载开头  tokenHead: Bearer
  4. 在 pojo 包下新建实体类

    LoginUser:用户验证登录用的实体类

    package cn.edu.hziee.pojo;import com.baomidou.mybatisplus.annotation.TableName;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import org.springframework.beans.factory.annotation.Autowired;@Data@NoArgsConstructor@AllArgsConstructor@TableName("user")public class UserLogin {    private Integer id;    private String name;    private String pwd;}
  5. 在 mapper 包下新建 UserMapper 接口

    package cn.edu.hziee.mapper;import cn.edu.hziee.bean.UserLogin;import cn.edu.hziee.pojo.User;import com.baomidou.mybatisplus.core.mapper.BaseMapper;import com.baomidou.mybatisplus.core.metadata.IPage;public interface UserMapper extends BaseMapper<UserLogin> {}
  6. 在 service 包下新建 UserService

    package cn.edu.hziee.service;import cn.edu.hziee.bean.UserLogin;import cn.edu.hziee.pojo.User;import com.baomidou.mybatisplus.extension.service.IService;import java.util.List;public interface UserService extends IService<UserLogin> {    List<User> getUserByGender(String gender, int current, int sine);    UserLogin login(String name, String pwd);}
  7. UserServiceImpl

    package cn.edu.hziee.service.impl;import cn.edu.hziee.bean.UserLogin;import cn.edu.hziee.mapper.UserMapper;import cn.edu.hziee.pojo.User;import cn.edu.hziee.service.UserService;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.baomidou.mybatisplus.core.metadata.IPage;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.List;@Servicepublic class UserServiceImpl extends ServiceImpl<UserMapper, UserLogin> implements UserService {    @Autowired    UserMapper userMapper;    @Override    public UserLogin login(String name, String pwd) { QueryWrapper<UserLogin> wrapper = new QueryWrapper(); wrapper.eq("name",name); UserLogin user = userMapper.selectOne(wrapper); if (user != null){     return user; } throw new RuntimeException("登陆失败~~~");    }}
  8. UserController

    package cn.edu.hziee.controller;import cn.edu.hziee.bean.UserLogin;import cn.edu.hziee.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;import java.util.HashMap;import java.util.Map;@Controller@RequestMapping("/user")public class UserController {    @Autowired    private UserService userService;    @ResponseBody    @PostMapping("/login")    public Map<String, Object> login(String name, String pwd) { Map<String, Object> map = new HashMap<>(); try {     UserLogin userLogin = userService.login(name, pwd);     map.put("state", true);     map.put("msg", "认证成功"); } catch (Exception e) {     map.put("state", false);     map.put("msg", e.getMessage()); } return map;    }}
  9. 启动类

    package cn.edu.hziee;import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication@MapperScan("cn.edu.hziee.mapper")public class MainApplication {    public static void main(String[] args) { SpringApplication.run(MainApplication.class,args);    }}
  10. 使用 Postman 进行环境的测试
    PostMan测试环境

    {    "msg": "认证成功",    "state": true}

7.1、生成 token 令牌

LoginController

package cn.edu.hziee.controller;import cn.edu.hziee.bean.UserLogin;import cn.edu.hziee.config.JWTUtil;import cn.edu.hziee.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;import java.util.HashMap;import java.util.Map;@Controller@RequestMapping("/user")public class UserController {    @Autowired    private UserService userService;    @Autowired    private JWTUtil jwtUtil;    @ResponseBody    @PostMapping("/login")    public Map<String, Object> login(String name, String pwd) { Map<String, Object> map = new HashMap<>(); try {     UserLogin userLogin = userService.login(name, pwd);     Map<String,Object> payload = new HashMap<>();     payload.put("id",userLogin.getId());     payload.put("name",userLogin.getName());     String token = jwtUtil.generateToken(payload);     map.put("token",token);     map.put("state", true);     map.put("msg", "认证成功"); } catch (Exception e) {     System.out.println("11111");     map.put("state", false);     map.put("msg", e.getMessage()); } return map;    }}

用接口 Postman 进行接口测试
在这里插入图片描述

{    "msg": "认证成功",    "state": true,    "token": "eyJUeXBlIjoiSnd0IiwidHlwIjoiSldUIiwiYWxnIjoiSFMyNTYifQ.eyJjcmVhdGVUaW1lIjoxNjMzMTU4ODE0LCJuYW1lIjoi5p2O5ZubIiwiaWQiOjIsImV4cCI6MTYzNTM5NDAxNH0.baFHLoiQluXLk1Zpy3STSEK0uVkwkj2T-RoqOdKARPc"}

7.2、验证 token 令牌

@ResponseBody@RequestMapping("tomain")public Map<String, Object> toMain(String token){    Map<String, Object> map = new HashMap<>();    try{ DecodedJWT verify = jwtUtil.verify(token); map.put("state", true); map.put("msg", "请求成功"); return map;    } catch (InvalidClaimException e){ map.put("msg", "失效的payload异常"); e.printStackTrace();    } catch (JWTDecodeException e){ map.put("msg", "JWT解码异常"); e.printStackTrace();    }catch (SignatureVerificationException e){ map.put("msg", "签名不一致"); e.printStackTrace();    }catch (TokenExpiredException e){ map.put("msg", "令牌过期异常"); e.printStackTrace();    }catch (AlgorithmMismatchException e){ map.put("msg", "算法不匹配异常"); e.printStackTrace();    }catch (Exception e){ map.put("msg", "token无效"); e.printStackTrace();    }    map.put("state", false);    return map;}

用接口 Postman 进行接口测试
在这里插入图片描述

{    "msg": "请求成功",    "state": true}

在每个需要 token 验证的接口加上以上代码,会造成大量的代码冗余

7.3、JWT 拦截器

  1. 在 Interceptors 包下新建一个 InterceptorProperties 类(用于存储 application.yml 中的配置参数)

    package cn.edu.hziee.Interceptors;import lombok.Data;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Component;@Component@Datapublic class InterceptorProperties {    @Value("${jwt.secretKey}")    private String secretKey;    @Value("${jwt.expiration}")    private Long expiration;}
  2. JWTInterceptor

    package cn.edu.hziee.Interceptors;import cn.edu.hziee.bean.UserLogin;import cn.edu.hziee.config.JWTUtil;import com.auth0.jwt.exceptions.*;import com.fasterxml.jackson.databind.ObjectMapper;import lombok.Data;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.util.HashMap;import java.util.Map;@Data@Componentpublic class JWTInterceptor implements HandlerInterceptor {    private InterceptorProperties interceptorProperties;    private static JWTUtil jwtUtil;    @Autowired    private void setJWTUtil(JWTUtil jwtUtil){ JWTInterceptor.jwtUtil = jwtUtil;    }    public JWTInterceptor(InterceptorProperties interceptorProperties) { this.interceptorProperties = interceptorProperties;    }    @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request.getHeader("token"); Map<String, Object> map = new HashMap<>(); try{     String secretKey = interceptorProperties.getSecretKey();     jwtUtil.verify(token);     return true; } catch (InvalidClaimException e){     map.put("msg", "失效的payload异常");     e.printStackTrace(); } catch (JWTDecodeException e){     map.put("msg", "JWT解码异常");     e.printStackTrace(); }catch (SignatureVerificationException e){     map.put("msg", "签名不一致");     e.printStackTrace(); }catch (TokenExpiredException e){     map.put("msg", "令牌过期异常");     e.printStackTrace(); }catch (AlgorithmMismatchException e){     map.put("msg", "算法不匹配异常");     e.printStackTrace(); }catch (Exception e){     map.put("msg", "token无效");     e.printStackTrace(); } map.put("state", false); String json = new ObjectMapper().writeValueAsString(map); response.setContentType("application/json;charset=UTF-8"); response.getWriter().println(json); return false;    }}
  3. InterceptorConfig

    package cn.edu.hziee.config;import cn.edu.hziee.Interceptors.InterceptorProperties;import cn.edu.hziee.Interceptors.JWTInterceptor;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configurationpublic class InterceptorConfig implements WebMvcConfigurer {    @Autowired    private InterceptorProperties interceptorProperties;    @Override    public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new JWTInterceptor(interceptorProperties))  .addPathPatterns("/user/tomain")  .excludePathPatterns("/user/login");    }}
  4. 用接口 Postman 进行接口测试

在这里插入图片描述

token 由前端存储在 localStorage 中

SpringBoot 整合 JWT(基于jwt) 《新程序员》:云原生和全面数字化实践 SpringBoot 整合 JWT(基于jwt) 50位技术专家共同创作,文字、视频、音频交互阅读