学习java认证授权之JWT之拦截器和过滤器01

  • Post author:
  • Post category:java


我喜欢别人老婆,你是不是觉得我很变态,换句话说,我喜欢很多年的人,已经结婚了.

—–2023-3-3前言

拦截器和和过滤器就是范围不同

请求>>

过滤器

>>mvc>>

拦截器

>>controller(javabean)>>

拦截器

>>mvc>>

过滤器

>>数据响应

先整boot和jwt版本

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.5.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.10.3</version>
</dependency>

附上学习资料


http://t.csdn.cn/UnJsY


http://t.csdn.cn/OGTPG

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的实例,因此使用会更方便。

get面试总结


区别:

执行流程不一样 过滤器属于tomacat容器,拦截属于spring,并且无缝衔接,过滤器基于回调函数,拦截器spring 并且过滤器在拦截器之前开始 在拦截器结束之后结束


怎么使用拦截器:

自定义如下,

package com.zhsp.interceptor;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.zhsp.common.AuthErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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;

public class AuthenticationInterceptor implements HandlerInterceptor {
   /**
     * 预处理回调方法,实现处理器的预处理(如检查登陆),第三个参数为响应的处理器,自定义Controller
     * 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断
     *  (如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
   */
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
        // 从 http 请求头中取出 token
        String token = httpServletRequest.getHeader("token");

        // 如果不是映射到方法直接通过
        if(!(object instanceof HandlerMethod)){
            return true;
        }
        HandlerMethod handlerMethod=(HandlerMethod)object;
        Method method=handlerMethod.getMethod();


        //判断如果请求的类是swagger的控制器,直接通行。
        if(handlerMethod.getBean().getClass().getName().equals("springfox.documentation.swagger.web.ApiResourceController")){
            return  true;
        }
        //跳过passtoken
        if (method.isAnnotationPresent(PassToken.class)) {
            PassToken passToken = method.getAnnotation(PassToken.class);
            if (passToken.required()) {
                return true;
            }
        }

        return true;
    }
    
    /**
     * 后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以
     * 通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
       */
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        UserHolder.removeUser();
        HandlerInterceptor.super.afterCompletion(httpServletRequest, httpServletResponse, o, e);
    }
}

注册到mvc

package com.zhsp.interceptor;

import org.springframework.context.annotation.Bean;
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 {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authenticationInterceptor())
                .addPathPatterns("/**")    // 拦截所有请求,通过判断是否有 @LoginRequired 注解 决定是否需要登录
                .excludePathPatterns(
                        "/config/**",
                        "/swagger-resources/**",
                        "/swagger-ui.html",
                        "/error",
                        "/doc.html",
                        "/v2/api-docs/**",
                        "/v2/api-docs-ext/**",
                        "/login/login",
                        "/file/richTextupload",
                        "/register/**",
                        "/app/**"
                ).addPathPatterns("app/common/**");
    }
    @Bean
    public AuthenticationInterceptor authenticationInterceptor() {
        return new AuthenticationInterceptor();
    }
}


可以使用的地方:

1.登录验证,判断用户是否登录。

2.权限验证,判断用户是否有权限访问资源,如校验token

3.日志记录,记录请求操作日志(用户ip,访问时间等),以便统计请求访问量。

4.处理cookie、本地化、国际化、主题等。

5.性能监控,监控请求处理时长等。

6.通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个处理器都需要的即可使用拦截器实现)


流程


1、拦截器执行顺序是按照Spring配置文件中定义的顺序而定的。


2、会先按照顺序执行所有拦截器的preHandle方法,一直遇到return false为止,比如第二个preHandle方法是return false,则第三个以及以后所有拦截器都不会执行。若都是return true,则按顺序加载完preHandle方法。


3、然后执行主方法(自己的controller接口),若中间抛出异常,则跟return false效果一致,不会继续执行postHandle,只会倒序执行afterCompletion方法。


4、在主方法执行完业务逻辑(页面还未渲染数据)时,按倒序执行postHandle方法。若第三个拦截器的postHandle方法return false,则会执行第二个和第一个的postHandle方法和afterCompletion(postHandle都执行完才会执行这个,也就是页面渲染完数据后,执行after进行清理工作)方法。(postHandle和afterCompletion都是倒序执行)



版权声明:本文为m0_62472302原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。