SpringBoot 整合 JWT 实战(基于jwt)

本文档详细介绍了如何在SpringBoot项目中整合JWT(JSON Web Token)进行用户身份验证和授权。首先创建了用户表并导入相关依赖,接着配置了数据库连接、mybatis-plus以及JWT的相关参数。然后定义了User实体类、UserMapper接口、UserService及其实现类,实现了用户登录功能。通过Postman测试登录接口,成功后生成JWT token。之后创建JWT拦截器处理token验证,避免重复代码。最后配置拦截器,使特定接口需要token验证。整个流程展示了JWT在SpringBoot应用中的完整应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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. 导入依赖:

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

    server:
      port: 8080
    
    spring:
      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.DruidDataSource
    
    logging:
      level:
        root: info
        cn.edu.hziee: debug
    
    mybatis-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;
    
    @Service
    public 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
    @Data
    public 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
    @Component
    public 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;
    
    @Configuration
    public 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 中

上一篇:JWT实现及工具类编写(使用jwt)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bit-apk-code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值