Spring MVC 拦截器

如何实现session共享问题:

1、session都在内存里面存储的,只要有session对象我都分发出去,让其他应用都可以拿到(同步)

缺点:只要有session对象都要广播出去,而且用户应用比较多了就会导致服务压力大,

2、使用token,登录完之后给你一个token,然后加密完之后发给服务器,用的时候直接把token给带过来即可,别的应用调用的时候就会拿到token相应的信息,这样就解决了session共享问题。

Spring MVC 的拦截器(Interceptor)与 Java Servlet 的过滤器(Filter)类似,它主要用于拦截用户的请求并做相应的处理,通常应用在权限验证、记录请求信息的日志、判断用户是否登录等功能上。

1.1 拦截器的定义

在 Spring MVC 框架中定义一个拦截器需要对拦截器进行定义和配置,

定义一个拦截器可以通过两种方式:

  • 一种是通过实现 HandlerInterceptor 接口实现类来定义;
  • 一种是通过实现 WebRequestInterceptor 接口继承 WebRequestInterceptor 接口的实现类来定义

代码编辑在interceptor包下创建

public class TokenInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, 
                HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle方法处理控制器(controller)方法调用之前");
        String token=request.getParameter("token");
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, 
                 Object handler, ModelAndView modelAndView) throws Exception {
  System.out.println("preHandle方法处理控制器(controller)方法调用之后,在解析视图之前执行");
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, 
                     Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion在视图渲染之后执行");
    }
}

配置类里面配置拦截器

@EnableWebMvc
@Configuration
public class WebConfig  implements  WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
      registry.addInterceptor(new TokenInterceptor()).addPathPatterns("/**");
    }

对token进行验证判断:

 @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle方法处理控制器(controller)方法调用之前");
        String token=request.getParameter("token");
        //对token进行判断
        if(token !=null && token.equals("206")){
            return true;
        }
        System.out.println("不是206学员");
        return false;
    }

访问测试:http://localhost:8080/gff/mother?token=206

如果被拦截了,是不是要给一个响应信息,或错误信息。

另外jwt里面也介绍说明:需要放到请求头里面

JWT跨域认证解决方案_赵同学&的博客-CSDN博客

运行测试:

除了返回状态码还可以指定放回格式:

@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle方法处理控制器(controller)方法调用之前");
        //获取请求头 getheader
        String token=request.getHeader("token");
        if(token !=null && token.equals("206")){
            return true;
        }
        System.out.println("不是正牌男友");
        //错误状态码
       // onse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        //指定返回格式
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write("{\"code\":401,\"message\":\"token必须传入\"}");
        return false;
    }

如果第一个拦截器出现问题了怎么办? 可以在添加一个:新创建一个SexInterceptor

public class SexInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle方法处理控制器(controller)方法调用之前");
        String token=request.getParameter("sex");
        if(token !=null && token.equals("girl")){
            return true;
        }
        System.out.println("什么玩意");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        return false;
    }

配置类配置:多拦截配置

@Override
    public void addInterceptors(InterceptorRegistry registry) {
        //order值越小越先执行
        registry.addInterceptor(new TokenInterceptor()).addPathPatterns("/**");
        registry.addInterceptor(new SexInterceptor()).addPathPatterns("/**");
    }

使用order调整顺序: order值越小越先执行

@Override
    public void addInterceptors(InterceptorRegistry registry) {
        //order值越小越先执行
        registry.addInterceptor(new TokenInterceptor()).addPathPatterns("/**").order(2);
        registry.addInterceptor(new SexInterceptor()).addPathPatterns("/**").order(1);
    }

放行验证:创建一个controller:

@RestController
@RequestMapping("/glf")
public class GirlFriendController {
​
    @GetMapping("/old")
    public String select(){
​
        return "这是你们前女友";
    }

比如针对性拦截:api路径 

@Override
    public void addInterceptors(InterceptorRegistry registry) {
        //order值越小越先执行
     registry.addInterceptor(new TokenInterceptor()).addPathPatterns("/api/**").order(2);
​
    }
public class TokenInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle方法在HandlerMethod执行之前");

        //获取token
        String token = request.getHeader("token");
        //如果token不为空,进行token验证
        if (token.equals("123456")) {
                return true;
            }
        //没有token,直接返回401
      //  response.setStatus(401);
        //或者
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write("{\"code\":401,\"message\":\"token必需传\"}");
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle方法在HandlerMethod调用之后,解析视图之前执行");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion方法在视图渲染结束之后执行");
    }
}

  在上述拦截器的定义中实现了 HandlerInterceptor 接口,并实现了接口中的 3 个方法。有关这 3 个方法的描述如下。

  • preHandle 方法:该方法在控制器的处理请求方法前执行,其返回值表示是否中断后续操作,返回 true 表示继续向下执行,返回 false 表示中断后续操作。

  • postHandle 方法:该方法在控制器的处理请求方法调用之后、解析视图之前执行,可以通过此方法对请求域中的模型和视图做进一步的修改。

  • afterCompletion 方法:该方法在控制器的处理请求方法执行完成后执行,即视图渲染结束后执行,可以通过此方法实现一些资源清理、记录日志信息等工作。

1.2 配置代码

@Configuration
//开启 Spring MVC注解驱动
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 可添加多个
         // order 谁小谁先拦截
        registry.addInterceptor(new TokenIntercepter()).addPathPatterns("/**").order(2);
        registry.addInterceptor(new SexIntercepter()).addPathPatterns("/**").order(1);
    }
    /**
     * 视图配置
     */
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        WebMvcConfigurer.super.configureViewResolvers(registry);
        registry.viewResolver(resourceViewResolver());
        /*registry.jsp("/WEB-INF/jsp/",".jsp");*/
    }

    /**
     * 配置请求视图映射
     */
    private InternalResourceViewResolver resourceViewResolver()
    {
        InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
        //请求视图文件的前缀地址
        internalResourceViewResolver.setPrefix("/WEB-INF/jsp/");
        //请求视图文件的后缀
        internalResourceViewResolver.setSuffix(".jsp");
        return internalResourceViewResolver;
    }
}

你可能感兴趣的:(springmvc,python,开发语言)