zoukankan      html  css  js  c++  java
  • Spring Boot拦截器实现并和swagger集成后使用拦截器的配置问题

    1. 定义拦截器 LoginInterceptor

    LoginInterceptor.java是整个登录认证模块中的核心类之一,它实现了HandlerInterceptor类,由它来拦截并过滤到来的每一个请求;它的三个方法能分别作用于每个请求的不同生命周期,你可以根据自己的需要来加入相应的处理逻辑

    package com.demo.common.interceptor;
    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.TypeReference;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.web.method.HandlerMethod;
    import org.springframework.web.multipart.MultipartHttpServletRequest;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.io.Reader;
    import java.io.StringWriter;
    import java.io.Writer;
    import java.lang.reflect.Type;
    import java.util.List;
    import java.util.Map;
    
    /**
     * @ProjectName: demo
     * @Package: com.demo.common.interceptor
     * @ClassName: LoginInterceptor
     * @Description: 登录请求拦截器
     * @Author:
     * @Date: 
     * @Version: 1.0
     */
    @Slf4j
    public class LoginInterceptor implements HandlerInterceptor {
    
      /**
       * 在请求被处理之前调用
       * @param request
       * @param response
       * @param handler
       * @return
       * @throws Exception
       */
      @Override
      public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
        String requestMethod = request.getMethod();
        if (requestMethod.contains("OPTIONS") || requestMethod.contains("options")) {
          return true;
        }
    
        //token 校验
        String token = request.getHeader("token");
        if (StringUtil.isEmpty(token)) {
          token = request.getHeader("token-inc");
        }
    
        //获取请求页面id
        String pageId = "";
        Map<String, String[]> paramMap = request.getParameterMap();
        if (CollectionUtils.isNotEmpty(paramMap)) {
          if (paramMap.containsKey("page_id")) {
            pageId = paramMap.get("page_id")[0];
          }
        }
    
        //验证token是否有效
        boolean checkToken = this.checkToken(token, pageId);
        if (!checkToken) {
          //未登录就跳转到登录页面
          //response.sendRedirect(LOGIN_HOST + "login");
          Result<String> resultObject = Result.fail("10001", "登录超时,请刷新页面重新登录");
          PrintWriter writer = response.getWriter();
          writer.write(JSON.toJSONString(resultObject));
          writer.flush();
          writer.close();
          return false;
        }
    
        //参数日志打印
        if (handler instanceof HandlerMethod) {
          this.saveRequestLog(request);
        }
        return true;
      }
    
      /**
       * 在请求被处理后,视图渲染之前调用
       * @param request
       * @param response
       * @param handler
       * @param modelAndView
       * @throws Exception
       */
      @Override
      public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        //Collection<String> headerNames = response.getHeaderNames();
        //log.info("[postHandle]{}", JsonUtils.toJson(headerNames));
      }
    
      /**
       * 在整个请求结束后调用
       * @param request
       * @param response
       * @param handler
       * @param ex
       * @throws Exception
       */
      @Override
      public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        UserInfoHolder.removeUserInfo();
      }
    
      /**
       * 请求校验token 塞入ThreadLocal
       *
       * @param token
       * @return
       */
      private boolean checkToken(String token, String pageId) {
        //不需要验证,直接通过,使用于直接请求接口(测试用)
        if ("false".equals(ENABLE_TOKEN) || NOT_VAILE_TOKEN.equals(token)) {
          return true;
        }
    
        if (StringUtil.isEmpty(token)) {
          return false;
        }
    
        //请求获取登录用户信息及权限
        HttpBO<UserInfoBO> httpBO = this.httpUserInfo(token, pageId);
    
        if (httpBO == null || httpBO.getCode() == null || httpBO.getCode() != 0 || httpBO.getData() == null) {
          return false;
        }
    
        this.saveLoginContext(httpBO.getData());
    
        return true;
      }
    
      private HttpBO<UserInfoBO> httpUserInfo(String token, String pageId) {
        HttpBO<UserInfoBO> httpBO = new HttpBO<>();
        try {
          LoginQuery loginQuery = new LoginQuery();
          loginQuery.setCookieStr(token);
          loginQuery.setPageId(pageId);
          String url = API_HOST + USER_URL;
          String jsonUserInfoBo = JSON.toJSONString(loginQuery);
          log.info("发送请求获取权限参数信息 param:{},url:{}", jsonUserInfoBo, url);
          String response = HttpClientPostUtil.sendPostRequest(url, jsonUserInfoBo);
          log.info("发送请求获取权限返回信息 response={}", response);
          Type type = new TypeReference<HttpBO<UserInfoBO>>() {
          }.getType();
          httpBO = JSON.parseObject(response, type);
          //httpBO = JSON.parseObject(response, new HttpBO<UserInfoBO>().getClass());
          log.info("发送请求获取权限信息 封装 httpBO:{}", JSON.toJSONString(httpBO));     
        } catch (Exception ex) {
          log.error("发送请求获取权限失败 error:{}", ex.getMessage());     
        }
        return httpBO;
      }
    
      private void saveLoginContext(UserInfoBO userInfoBO) {
        //List<ButtonBO> buttonBOList = userInfoBO.getUserBtns();
        //if (CollectionUtils.isEmpty(buttonBOList)) {
        //  List<String> code = buttonBOList.stream().map(ButtonBO::getBtnCode).collect(Collectors.toList());
        //}
    
        UserInfoHolder.setUserInfo(userInfoBO);
      }
    
      private void saveRequestLog(HttpServletRequest request) throws Exception {
        StringBuilder builder = new StringBuilder();
        builder.append("请求入口 ");
        builder.append("PATH => ");
        builder.append(request.getRequestURI());
        builder.append(",METHOD => ");
        builder.append(request.getMethod());
        builder.append(",PARAM => ");
        Map<String, String[]> paramMap = request.getParameterMap();
        if (CollectionUtils.isNotEmpty(paramMap)) {
          builder.append(JSON.toJSONString(paramMap));
          builder.append(",page_id => ");
          if (paramMap.containsKey("page_id")) {
            builder.append(paramMap.get("page_id")[0]);
          }
          log.info(builder.toString());
          return;
        }
        if (request instanceof MultipartHttpServletRequest) {
          log.info(builder.toString());
          return;
        }
        //由于request.getReader流只能操作一次,这里用过一次后,在Control中获取RequestBody中参数就获取不到,所以这里要先注释掉,后续解决
    //    BufferedReader reader = request.getReader();
    //    String body = this.read(reader);
    //    if (StringUtil.isNotEmpty(body)) {
    //      body = body.replace("
    ", "");
    //    }
    //    builder.append(body);
        log.info(builder.toString());
      }
    
      private String read(Reader reader) throws IOException {
        StringWriter writer = new StringWriter();
        try {
          this.write(reader, writer, 1024 * 8);
          return writer.getBuffer().toString();
        } finally {
          writer.close();
        }
      }
    
      private long write(Reader reader, Writer writer, int bufferSize) throws IOException {
        int read;
        long total = 0;
        char[] buf = new char[bufferSize];
        while ((read = reader.read(buf)) != -1) {
          writer.write(buf, 0, read);
          total += read;
        }
        return total;
      }
    
    }
    View Code

    2. 注册拦截器配置 LoginConfiguration

    LoginConfiguration.java是另一个核心类之一,它继承自WebMvcConfigurer类,负责注册并生效我们自己定义的拦截器配置;在这里要注意定义好拦截路径和排除拦截的路径;

    package com.demo.common.configuration;
    
    import com.demo.common.interceptor.LoginInterceptor;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    import org.springframework.web.servlet.handler.MappedInterceptor;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    /**
     * @ProjectName: demo
     * @Package: com.demo.common.configuration
     * @ClassName: LoginConfiguration
     * @Description: 负责注册并生效自己定义的拦截器配置
     * @Author:
     * @Date: 
     * @Version: 1.0
     */
    @Configuration
    public class LoginConfiguration implements WebMvcConfigurer {
      @Bean
      public MappedInterceptor getMappedInterceptor() {
        //注册拦截器
        LoginInterceptor loginInterceptor = new LoginInterceptor();
        //拦截路径 ("/**")对所有请求都拦截
        String[] includePatterns = new String[]{"/**"};
        //排除拦截路径
        String[] excludePatterns = new String[]{"/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**",
          "/api", "/api-docs", "/api-docs/**"};
    
        //将数组转化为集合
        List<String> listOldExclude = Arrays.asList(excludePatterns);
    
        //将自定义的排除拦截路径添加到集合中
        List<String> listNewExclude = new ArrayList<>();
        listNewExclude.add("/demoJson/getCityList.json");
        listNewExclude.add("/demoJson/getStudentList.json");
        
        //定义新集合
        List<String> listExclude = new ArrayList<>();
        listExclude.addAll(listOldExclude);
        listExclude.addAll(listNewExclude);
    
        //将新集合转化回新数组
        String[] newExcludePatterns = listExclude.toArray(new String[listExclude.size()]);
    
        return new MappedInterceptor(includePatterns, newExcludePatterns, loginInterceptor);
      }
    }
    View Code
  • 相关阅读:
    Mysql表连接查询
    mysql查询语句 和 多表关联查询 以及 子查询
    MySql 模糊查询、范围查询
    Mysql外键约束设置使用方法
    python基础:re模块匹配时贪婪和非贪婪模式
    解决Ubuntu 16.04下提示boot分区空间不足的办法
    String,StringBuffer,StringBuilder的区别
    多线程模拟生产者和消费者模型
    线程同步处理
    多线程的三种实现
  • 原文地址:https://www.cnblogs.com/li150dan/p/12072023.html
Copyright © 2011-2022 走看看