springboot的jwt、过滤器、拦截器

1、jwt令牌

1、是一种开放标准,定义了一种紧凑的、自包含的方式,用于作为不同域之间的两方之间安全地表示声明
2、导包
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.5</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>
3、导入工具类,jwt生成与检验参考工具类中main中的用法
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;

import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JWTUtil {

    private static final Key SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);

    public static String generateToken(Map<String, Object> claims, int expirationSeconds) {
        return Jwts.builder()
                .setClaims(claims)
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis() + expirationSeconds * 1000L))
                .signWith(SECRET_KEY, SignatureAlgorithm.HS256)
                .compact();
    }

    public static Claims validateToken(String token) {
        try {
            return Jwts.parserBuilder()
                    .setSigningKey(SECRET_KEY)
                    .build()
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            throw new RuntimeException("Token校验失败: " + e.getMessage());
        }
    }

    public static void main(String[] args) {
        // 示例数据
        Map<String, Object> claims = new HashMap<>();
        claims.put("user_id", 123);
        claims.put("username", "example_user");

        // 生成JWT
        String token = generateToken(claims, 3600); // 有效期1小时
        System.out.println("生成的JWT令牌: " + token);

        // 校验JWT
        try {
            Claims validatedClaims = validateToken(token);
            System.out.println("校验成功,解码后的数据: " + validatedClaims);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

2、过滤器(Filter)

1、会拦截所有的资源
2、springboot启动类上添加@ServletComponentScan注解
3、自定义类TokenFilter实现Filter接口
package com.example.config;

import com.example.tool.JWTUtil;
import io.jsonwebtoken.Claims;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
@Slf4j
@WebFilter(urlPatterns = "/*")//过滤所有路径
public class TokenFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String url = request.getRequestURL().toString();
        String token = request.getHeader("token");

        //登录放行
        if (url.contains("login")) {
            filterChain.doFilter(request, response);
            return;
        }

        //token为空,不放行
        if (token == null || token == "") {
            response.setStatus(401);//设置状态码401,要求前端跳转登录页面
            log.error("token is Empty");
            return;
        } else {
            try {
                //token校验成功,放行
                Claims validatedClaims = JWTUtil.validateToken(token);
                System.out.println("校验成功,解码后的数据: " + validatedClaims);
                filterChain.doFilter(request, response);
            } catch (Exception e) {
                e.printStackTrace();
                log.error("token is Error");
                //token校验失败
                response.setStatus(401);//设置状态码401,要求前端跳转登录页面
            }
        }
    }
}

3、拦截器(Interceptor)

1、只会拦截Spring环境中的资源
2、自定义类MyInterceptor 实现HandlerInterceptor 接口
package com.example.config;

import com.example.tool.JWTUtil;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

@Slf4j
@Component
public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String url = request.getRequestURL().toString();
        String token = request.getHeader("token");

        //登录放行,在配置类里写了,此次不需要了
        /*if(url.contains("login")){
            return true;
        }*/

        if(token==null || token==""){
            response.setStatus(401);//设置状态码401,要求前端跳转登录页面
            log.error("Myhandler:token is Empty");
            return false;
        }
        else {
            try {
                Claims validatedClaims = JWTUtil.validateToken(token);
                System.out.println("校验成功,解码后的数据: " + validatedClaims);
                return true;
            } catch (Exception e) {
                response.setStatus(401);//设置状态码401,要求前端跳转登录页面
                log.error("Myhandler:token is Error");
                e.printStackTrace();
                return false;
            }
        }

    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

3、在一个配置类中注册它,并指定要拦截的路径模式
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 WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor())
                .addPathPatterns("/api/**") // 拦截所有以 /api/ 开头的请求
                .excludePathPatterns("/api/public/**"); // 排除以 /api/public/ 开头的请求
    }
}
### Spring Boot 中实现 JWT 拦截器Spring Boot应用中集成JWT(JSON Web Token)用于认证和授权,通常会通过自定义拦截器过滤器来处理HTTP请求。下面展示一种常见的做法,即创建一个名为`JwtRequestFilter.java`的类作为过滤器[^2]。 #### 创建 JwtRequestFilter 类 此Java类负责提取并验证传入请求中的Token有效性: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @Component public class JwtRequestFilter extends OncePerRequestFilter { @Autowired private MyUserDetailsService userDetailsService; @Autowired private JwtUtil jwtUtil; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { final String authorizationHeader = request.getHeader("Authorization"); String username = null; String jwt = null; if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) { jwt = authorizationHeader.substring(7); try{ username = jwtUtil.extractUsername(jwt); // 解析token获取用户名 }catch(Exception e){ logger.error(e.getMessage()); } } if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); if (jwtUtil.validateToken(jwt, userDetails)) { // 验证token合法性 UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(authentication); } } chain.doFilter(request, response); } } ``` 上述代码片段展示了如何构建一个简单的JWT请求过滤器,它会在每次接收到新的HTTP请求时自动触发执行。当检测到有效的JWT令牌后,则设置当前线程的安全上下文以便后续操作能够识别已认证的身份信息。 #### 应用程序配置文件(application.yml) 为了让应用程序知道去哪里查找这些安全相关的属性值,可以在项目的根目录下找到`application.yml`文件,并添加如下所示的内容以指定密钥和其他必要的参数[^4]: ```yaml # JWT 配置 jwt: secret: your_secret_key_here # 替换成实际使用的秘钥字符串 expiration: 86400 # 设置过期时间为一天(秒) header: "Authorization" token-prefix: "Bearer " ``` 以上就是关于如何在Spring Boot框架内利用JWT技术完成身份验证机制的大致流程说明。需要注意的是,在真实环境中还需要考虑更多细节问题比如异常处理、日志记录等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值