在Spring Boot应用开发中,Filter和Interceptor是两个重要的机制,它们用于请求的预处理和后处理,广泛应用于安全、日志记录、性能监控及其他功能的实现中。本文将对此进行深入探讨,并通过登录校验的例子来演示如何使用Filter、Interceptor和JWT令牌。

Filter与Interceptor的区别

  1. Filter
  2. 源于Servlet规范,主要用于对请求和响应进行过滤。
  3. 在请求到达Servlet之前和响应返回给客户端之后执行。
  4. 适用于统一处理某些特征的请求,例如权限认证、日志记录、压缩等。

  5. Interceptor

  6. Spring框架提供的功能,主要用于对Controller方法的调用进行拦截。
  7. 仅在Spring MVC中有效,无法对所有请求作出响应。
  8. 更适合处理Spring特有的逻辑,例如视图解析、方法调用前后处理等。

登录校验示例

在本示例中,我们将通过Filter实现JWT令牌的验证,同时使用Interceptor进行登录状态的检查。

1. 添加依赖

pom.xml中添加相关依赖(例如Spring Boot Starter Web和JWT库):

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.9.1</version>
    </dependency>
</dependencies>

2. 创建JWT工具类

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.Date;

public class JwtUtil {

    private static final String SECRET_KEY = "your_secret_key";

    public static String createToken(String username) {
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);

        JwtBuilder builder = Jwts.builder()
                .setSubject(username)
                .setIssuedAt(now)
                .setExpiration(new Date(nowMillis + 3600000)) // 1小时过期
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY);

        return builder.compact();
    }

    public static Claims validateToken(String token) {
        return Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token)
                .getBody();
    }
}

3. 创建Filter

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

public class JwtFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String token = httpRequest.getHeader("Authorization");

        if (token != null && token.startsWith("Bearer ")) {
            token = token.substring(7); // 移除“Bearer ”部分
            try {
                Claims claims = JwtUtil.validateToken(token);
                // TODO: 可以设置用户信息到上下文中
                System.out.println("用户: " + claims.getSubject());
            } catch (Exception e) {
                throw new ServletException("无效的令牌.");
            }
        }

        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
    }
}

4. 注册Filter

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<JwtFilter> jwtFilter() {
        FilterRegistrationBean<JwtFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new JwtFilter());
        registrationBean.addUrlPatterns("/api/*"); // 过滤器应用于特定路径
        return registrationBean;
    }
}

5. 创建Interceptor

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // TODO: 检查用户是否登录
        boolean isLoggedIn = true; // 此处可用实际逻辑判断
        if (!isLoggedIn) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }
        return true;
    }
}

6. 注册Interceptor

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 WebConfig implements WebMvcConfigurer {

    @Autowired
    private LoginInterceptor loginInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor).addPathPatterns("/api/**");
    }
}

总结

通过以上示例,我们展示了如何在Spring Boot应用中结合使用Filter和Interceptor来实现JWT令牌的验证和登录校验。Filter负责对每个请求的JWT进行验证,而Interceptor则是用来检查用户的登录状态。这种结合使得极大增强了应用的安全性,同时保持代码的清晰和结构化。

点赞(0) 打赏

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部