SpringBoot配置JWT拦截器

目录

1.背景介绍

2.前提工作

3.具体代码

(1)相关依赖

(2)相关配置文件

(3)JwtUtils类

(4)准备好登录逻辑代码(Dao、Service、Controller)

(5)拦截器JwtInterceptor类

(6)注册拦截器到配置类

4. 测试


1.背景介绍

        JWT在之前文章提到过,JWT(JSON Web Token)是一种用于身份验证和授权的开放标准(RFC 7519),它允许在网络中安全地传输声明(claims)作为 JSON 对象。JWT 可以通过数字签名或加密来验证数据的完整性和真实性,从而保证数据在传输过程中不被篡改。

        工作流程

  1. 用户通过用户名和密码等方式进行身份验证。
  2. 服务器验证用户身份,并生成一个 JWT。
  3. 服务器将 JWT 发送给客户端
  4. 客户端将 JWT 存储起来,通常是在本地存储或者内存中。
  5. 客户端将 JWT 添加到每个后续的 HTTP 请求的 Authorization 头部中。
  6. 服务器收到请求后,解析 JWT 并验证签名。
  7. 如果验证通过,则处理请求;如果验证失败,则拒绝请求。

2.前提工作

        1.Redis,用于将生成的token存入其中

        2.用户登录Controller

        3.Jwtutils、相关依赖

        4.拦截器JwtInterceptor

        5.配置类WebMvcConfig,用于注册拦截器

3.具体代码

(1)相关依赖
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-api</artifactId>
            <version>0.11.2</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-impl</artifactId>
            <version>0.11.2</version>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-jackson</artifactId>
            <version>0.11.2</version>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
(2)相关配置文件
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/login?useSSL=false&serverTimezone=UTC
    username: #自己的数据库用户名
    password: #自己的数据库密码

  redis:
    host: localhost
    port: 6379


mybatis:
  mapper-locations: classpath:mapper/*.xml


jwt:
  secret: T7e3t3AhK9kS2DdF6gZr4e7hWmYq3t5vT7e3t3AhK9kS2DdF6gZr4e7hWmYq3t5vT7e3t3AhK9kS2DdF6gZr4e7hWmYq3t5vT7e3t3AhK9kS2DdF6gZr4e7hWmYq3t5v
  expiration: 864000
(3)JwtUtils类
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.concurrent.TimeUnit;

@Component
public class JwtUtils {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    @Value("${jwt.secret}")
    private String secret;

    @Value("${jwt.expiration}")
    private  long expiration;

    /**
     * 生成token
     * @param username
     * @return
     */
    public  String generateToken(String username) {
        String token = Jwts.builder()
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + expiration))
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();

        // 将 Token 存储到 Redis 中
        redisTemplate.opsForValue().set(username, token, expiration, TimeUnit.MILLISECONDS);

        return token;
    }

    /**
     * 验证token
     * @param token
     * @return
     */
    public boolean validateToken(String token) {
        // 从 Token 中获取用户名
        String username = getUsernameFromToken(token);

        // 从 Redis 中获取存储的 Token
        String storedToken = redisTemplate.opsForValue().get(username);

        // 判断 Redis 中存储的 Token 是否与传入的 Token 相同
        return storedToken != null && storedToken.equals(token);
    }

    /**
     * 删除token
     * @param username
     */
    public void removeToken(String username) {
        // 从 Redis 中删除 Token
        redisTemplate.delete(username);
    }

    /**
     * 根据token获取用户信息
     * @param token
     * @return
     */
    public String getUsernameFromToken(String token) {
        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(secret).parseClaimsJws(token);
        Claims claims = claimsJws.getBody();
        return claims.getSubject();
    }

    /**
     * 判断token是否存在
     * @param username
     * @return
     */
    public String getTokenIfExists(String username) {
        // Check if a valid token exists in Redis for the given username
        String storedToken = redisTemplate.opsForValue().get(username);

        // Validate the stored token
        if (storedToken != null && validateToken(storedToken)) {
            return storedToken;
        } else {
            return null;
        }
    }


}
(4)准备好登录逻辑代码(Dao、Service、Controller)
import com.zhan.zhan215.Entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

@Mapper
public interface UserMapper{

        User getUserByUsernameAndPassword(@Param("username")String username,@Param("password")String password);


}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhan.zhan215.Dao.UserMapper">

    <select id="getUserByUsernameAndPassword" parameterType="com.zhan.zhan215.Entity.User" resultType="com.zhan.zhan215.Entity.User">

        select *
        from user
        WHERE username = #{username} AND password = #{password}

    </select>

</mapper>
@RestController
@RequestMapping("/user")
@Api(tags = "User API", description = "Operations for managing users")
public class UserController {

       @Resource
       private UserService userService;

       @Resource
       private JwtUtils jwtUtils;


       @PostMapping("/login")
       @ApiOperation(value = "登录控制器")
       public ResponseBean login(@RequestParam(value = "username") String username, @RequestParam(value = "password") String password) {

           User user1 = userService.getUserByUsernameAndPassword(username, password);

           System.out.println(user1);

           if(user1!=null) {
               // 检查用户是否有token
               String existingToken = jwtUtils.getTokenIfExists(username);

               if(existingToken!=null){

                   return ResponseBean.success("已存在token,无需重复登录",existingToken);

               }else{

                   // 生成token
                   String token = jwtUtils.generateToken(username);
                   System.out.println(token);
                   return ResponseBean.success("登录成功", token);

                   // 将token返回给前端
               }

           }
           return ResponseBean.error("用户名或密码错误");

       }

       @GetMapping("/get")
       public ResponseBean getAll(@RequestHeader("Authorization") String token){

           if(jwtUtils.validateToken(token)){

               return ResponseBean.success(userMapper.getAll());

               }

           else{

               return ResponseBean.error("token无效");

           }
             // 倘若不写拦截器 则每个请求方法都要像getAll这样去做判断,非常麻烦

       }

       @GetMapping("/getAllByPage")
       public ResponseBean getAllByPage(@RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "2") Integer size) {

          return ResponseBean.success(userService.getAllByPage(page, size));

       }
}
(5)拦截器JwtInterceptor类
import com.zhan.zhan215.Utils.JwtUtils;
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;


@Component
public class JwtInterceptor implements HandlerInterceptor {


    @Autowired
    private JwtUtils jwtUtils;


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 从请求头中获取 token
        String token = request.getHeader("Authorization");

        // 验证 token
        if (token != null && jwtUtils.validateToken(token)) {

            return true; // 验证通过,继续处理请求

        } else {
            // 设置响应状态码为 401
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

            // 设置响应内容为 JSON 格式的错误信息
            String errorMessage = "{\"error\": \"token无效\"}";
            response.setContentType("application/json");
            response.setCharacterEncoding("UTF-8");
            response.getWriter().write(errorMessage);

            return false; // 验证失败,不继续处理请求

        }



    }

}
(6)注册拦截器到配置类
import com.zhan.zhan215.Interceptor.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 WebMvcConfig  implements WebMvcConfigurer {

    @Autowired
    private JwtInterceptor jwtInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(jwtInterceptor)
                .addPathPatterns("/user/getAllByPage")// 配置拦截路径,这里假设所有 API 都需要验证 token
                .excludePathPatterns("/user/search");// 这是可以排除的路径,
        // 比如登录接口,登录接口不需要 token 验证
        
        // 如果有多个拦截器,可以这样继续添加
        // registry.addInterceptor(jwtInterceptor).addPathPatterns("/user/login");
        // registry.addInterceptor(jwtInterceptor).addPathPatterns("/user/update");
        // registry.addInterceptor(jwtInterceptor).addPathPatterns("/user/delete");
        // registry.addInterceptor(jwtInterceptor).addPathPatterns("/user/getById");

    }

}

4. 测试

先进行登录:

在后端控制台查看token

未携带请求头:

携带请求头后:

说明拦截器生效

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
下面是一个使用 Spring BootJWT拦截器实现登录验证的示例代码: 1. 添加 JWT 依赖 在 pom.xml 文件中添加以下依赖: ```xml <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.11.2</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-impl</artifactId> <version>0.11.2</version> <scope>runtime</scope> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-jackson</artifactId> <version>0.11.2</version> <scope>runtime</scope> </dependency> ``` 2. 创建 JWT 工具类 ```java import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.security.Keys; import org.springframework.stereotype.Component; import java.security.Key; import java.util.Date; import java.util.HashMap; import java.util.Map; @Component public class JwtUtil { private final Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256); public String generateToken(String subject) { return Jwts.builder() .setClaims(new HashMap<>()) .setSubject(subject) .setExpiration(new Date(System.currentTimeMillis() + 60 * 60 * 1000)) .signWith(key) .compact(); } public boolean validateToken(String token) { try { Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token); return true; } catch (Exception e) { return false; } } public String getUsernameFromToken(String token) { Claims claims = Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody(); return claims.getSubject(); } } ``` 3. 创建拦截器 ```java import com.example.demo.jwt.JwtUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.lang.reflect.Method; @Component public class AuthenticationInterceptor implements HandlerInterceptor { @Autowired private JwtUtil jwtUtil; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request.getHeader("Authorization"); if (token != null && jwtUtil.validateToken(token)) { String username = jwtUtil.getUsernameFromToken(token); request.setAttribute("username", username); return true; } else { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return false; } } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { HandlerMethod handlerMethod = (HandlerMethod) handler; Method method = handlerMethod.getMethod(); LoginRequired loginRequired = method.getAnnotation(LoginRequired.class); if (loginRequired != null && modelAndView != null) { modelAndView.addObject("username", request.getAttribute("username")); } } } ``` 4. 创建注解 ```java import java.lang.annotation.*; @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface LoginRequired { } ``` 5. 创建控制器 ```java import com.example.demo.interceptor.LoginRequired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @GetMapping("/") public String index() { return "Hello World"; } @GetMapping("/hello") @LoginRequired public String hello() { return "Hello " + SecurityContextHolder.getContext().getAuthentication().getName(); } } ``` 6. 配置拦截器 ```java import com.example.demo.interceptor.AuthenticationInterceptor; 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 WebMvcConfig implements WebMvcConfigurer { @Autowired private AuthenticationInterceptor authenticationInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(authenticationInterceptor).addPathPatterns("/**"); } } ``` 7. 创建登录控制器 ```java import com.example.demo.jwt.JwtUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.Map; @RestController public class LoginController { @Autowired private JwtUtil jwtUtil; @PostMapping("/login") public Map<String, Object> login(@RequestBody Map<String, String> params) { String username = params.get("username"); String password = params.get("password"); // TODO: 验证用户名和密码 String token = jwtUtil.generateToken(username); Map<String, Object> result = new HashMap<>(); result.put("token", token); return result; } } ``` 在这个示例中,我们创建了一个 JWT 工具类来生成和验证 JWT,创建了一个拦截器来验证用户是否登录,并使用 @LoginRequired 注解来标记需要登录验证的方法。我们还创建了一个登录控制器来生成 JWT。通过这个示例,您可以了解如何使用 Spring BootJWT拦截器实现登录验证。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

蜗牛变涡流

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

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

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

打赏作者

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

抵扣说明:

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

余额充值