【SpringBoot项目】过滤器方式和拦截器方式进行登录校验-token

过滤器方式(不常用)

ServletConfig配置

@Configuration
@RequiredArgsConstructor
public class ServletConfig {


    //redisTemplate
    private final StringRedisTemplate redisTemplate;

    /**
     * @Author: pureyun
     * @Data: 2024/6/29 16:52
     * @Description: 配置原生filter,然后注册filter
     * @param
     * @return: org.springframework.boot.web.servlet.FilterRegistrationBean
     **/
    @Bean
    public FilterRegistrationBean filterRegistrationBean(){
        //创建FilterRegistrationBean的bean对象
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        //创建自定义过滤器
        LoginCheckFilter loginCheckFilter =new LoginCheckFilter(redisTemplate);
        //将自定义的过滤器注册到FilterRegistrationBean中
        filterRegistrationBean.setFilter(loginCheckFilter);
        //给过滤器指定拦截的请求
        //放行特定端口
        // 拦截所有请求
        filterRegistrationBean.addUrlPatterns("/*");
        return filterRegistrationBean;

    }
}

Filter(参考模板)

public class LoginCheckFilter implements Filter {


    private StringRedisTemplate redisTemplate;

    public LoginCheckFilter(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    //过滤器拦截到请求的方法
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        //先获得HttpServletRequest和HttpServletResponse
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;


        //白名单通过
        List<String> excludePath = new ArrayList<>();
        excludePath.add("/login");
        excludePath.add("/captcha/captchaImage");
        String servletPath = request.getServletPath();
        if (excludePath.contains(servletPath)) {
            filterChain.doFilter(request,response);
            return;
        }

        //其它请求都校验是否携带token,以及判断redis中是否存在token的键
        String token = request.getHeader(WarehouseConstants.HEADER_TOKEN_NAME);
        if (StringUtils.hasText(token) && redisTemplate.hasKey(token)) {
            //如果 str 是 null,返回 false。
            //如果 str 是空字符串(即长度为0),返回 false。
            //如果 str 只包含空白字符(如空格、制表符等),返回 false。
            //如果 str 包含至少一个非空白字符,返回 true。
            filterChain.doFilter(request, response);
            return;
        }
        //2没有,说明登录失败了
        Result result =Result.err(Result.CODE_ERR_UNLOGINED,"您尚未登录");
        String jsonString = JSON.toJSONString(result);
        response.setContentType("application/json;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.write(jsonString);
        out.flush();
        out.close();
    }
}

拦截器方式(常用)

WebConfig

@Configuration
@RequiredArgsConstructor
public class WebMvcConfig implements WebMvcConfigurer {

    private final LoginCheckInterceptor loginCheckInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //添加拦截器
        registry.addInterceptor(loginCheckInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/login","/captcha/captchaImage");
    }
}

LoginCheckInterceptor

@Component
@RequiredArgsConstructor
public class LoginCheckInterceptor implements HandlerInterceptor {

    private final StringRedisTemplate redisTemplate;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取token
        String token = request.getHeader(WarehouseConstants.HEADER_TOKEN_NAME);
        if(StringUtils.hasText(token)&&redisTemplate.hasKey(token)){
            return true;
        }
        Result result  = Result.err(Result.CODE_ERR_UNLOGINED,"没有权限访问");
        String jsonString = JSON.toJSONString(result);//获取json字符串
        response.setContentType("application/json;charset=utf-8");//设置返回类型
        PrintWriter out = response.getWriter();
        out.write(jsonString);
        out.flush();
        out.close();
        return false;
    }
}

小结

        1.我们可以从中发现,用servlet原生的方式进行登录权限控制更加麻烦,但是拦截器就比较方便。

面试题

拦截器和过滤器区别?

        直观回答:

1.过滤器可以修改request,而拦截器不能
2.过滤器需要在servlet容器中实现,拦截器可以适用于javaEE,javaSE等各种环境
3.拦截器可以调用IOC容器中的各种依赖,而过滤器不能
4.过滤器只能在请求的前后使用,而拦截器可以详细到每个方法

        客观回答:

1、过滤器和拦截器触发时机不一样,过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。

2、拦截器可以获取IOC容器中的各个bean,而过滤器就不行,因为拦截器是spring提供并管理的,spring的功能可以被拦截器使用,在拦截器里注入一个service,可以调用业务逻辑。而过滤器是JavaEE标准,只需依赖servlet api ,不需要依赖spring。

3、过滤器的实现基于回调函数。而拦截器(代理模式)的实现基于反射

4、Filter是依赖于Servlet容器,属于Servlet规范的一部分,而拦截器则是独立存在的,可以在任何情况下使用。

5、Filter的执行由Servlet容器回调完成,而拦截器通常通过动态代理(反射)的方式来执行。

6、Filter的生命周期由Servlet容器管理,而拦截器则可以通过IoC容器来管理,因此可以通过注入等方式来获取其他Bean的实例,因此使用会更方便。
————————————————
                        
推荐原文链接:https://blog.csdn.net/weixin_44830949/article/details/127493342

 

### 回答1: 可以通过实现 Filter 接口来创建一个过滤器,然后在 Spring Boot 中使用 @Bean 注解将其注册到应用程序中。在过滤器中,可以通过 HttpServletRequest 对象获取请求头中的 token,然后进行验证或者其他操作。具体实现可以参考 Spring Boot 官方文档或者相关教程。 ### 回答2: 在使用Spring Boot中,可以通过创建一个过滤器来拦截token。下面是一个简单的示例,说明如何实现。 首先,需要创建一个自定义的过滤器类,实现javax.servlet.Filter接口。在实现过滤器时,我们可以在doFilter方法中进行token验证的逻辑处理。以下是示例代码: ```java import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class TokenFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 将请求和响应对象转换成HttpServletRequest和HttpServletResponse对象 HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; // 从请求头中获取token String token = httpRequest.getHeader("Authorization"); // 进行token验证的逻辑处理,例如验证token是否过期、是否有效等 // ... // 如果验证通过,将请求继续传递给下一个过滤器或目标资源处理 chain.doFilter(request, response); } // 其他方法,例如init和destroy方法,可以留空不做处理 } ``` 接下来,需要将自定义的过滤器添加到Spring Boot应用程序中。可以使用@Configuration注解将过滤器添加为一个Bean,并使用@Order注解指定过滤器的执行顺序。例如: ```java import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; @Configuration public class FilterConfig { @Bean public FilterRegistrationBean<TokenFilter> tokenFilter() { FilterRegistrationBean<TokenFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new TokenFilter()); // 设置过滤器的URL映射规则,例如/*表示拦截所有请求 registrationBean.addUrlPatterns("/*"); // 设置过滤器的执行顺序 registrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE); return registrationBean; } } ``` 最后,重新启动Spring Boot应用程序,自定义的过滤器就会拦截所有请求,并对token进行验证处理。 请注意,上述示例只是一个简单的演示,实际应用中可能需要根据具体的需求进行修改和扩展。例如,可以从数据库或缓存中获取token进行更加复杂的验证逻辑,并在验证失败时返回相应的错误信息。 ### 回答3: 使用Spring Boot实现过滤器拦截Token的步骤如下: 1. 创建一个自定义的过滤器类,实现javax.servlet.Filter接口,并重写doFilter方法。在doFilter方法中,可以通过HttpServletRequest对象获取请求头中的Token信息,并进行相应的验证或处理。 2. 在Spring Boot应用的启动类中,通过添加注解@EnableWebSecurity开启Web安全配置,并通过继承WebSecurityConfigurerAdapter类重写configure方法。 3. 在configure方法中,使用http对象的addFilterBefore方法将自定义的过滤器添加到过滤器链中,指定过滤器在哪个过滤器之前进行拦截。 4. 在过滤器中,可以进行Token的验证和处理逻辑。例如,可以使用JWT来生成和验证Token,或将Token存储在Redis中,根据请求的Token进行校验等。 5. 如果Token验证不通过,可以返回相应的错误信息或重定向到登录页面。如果验证通过,可以进行其他的业务逻辑处理。 总之,通过自定义过滤器并将其添加到Spring Boot过滤器链中,可以在请求到达Controller之前进行Token的验证和拦截操作,以实现对请求的安全控制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

努力奋斗的张同学

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

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

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

打赏作者

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

抵扣说明:

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

余额充值