解决拦截器与swagger相互影响的问题

背景

spring-boot版本2.6.13
swagger版本2.9.2
拦截器本来好好的,项目中添加了swagger后拦截器失效了。

解决

参考:https://stackoverflow.com/questions/40241843/failed-to-start-bean-documentationpluginsbootstrapper-in-spring-data-rest

A
更改 spring 以使用 antmatchers 并在 application.properties 中配置它

spring.mvc.pathmatch.matching-strategy = ANT_PATH_MATCHER

B
在 spring 中启用 mvcmatchers 创建一个配置文件供 swagger 使用

在您想要的任何地方创建一个用于 swagger 配置的文件
添加这些注释

@EnableWebMvc
@EnableSwagger2
@Component
public class SwaggersConfigs {
}

C
在所有 Spring 应用程序中启用 mvcmatchers,将 @EnableWebMvc 注释放在 Spring Boot 应用程序的主类之上,如下所示

@EnableWebMvc
@EnableSwagger2
@SpringBootApplication
public class SwaggerDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SwaggerDemoApplication.class, args);
    }

}

我是在启动类Swagger的配置类上都加上了**@EnableWebMvc
@EnableSwagger2**,然后问题解决了。

完整示例

依赖

 <spring-boot.version>2.6.13</spring-boot.version>
 
        <!-- swagger -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>

Swagger配置类

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;

@Configuration
@EnableSwagger2
@EnableWebMvc
public class SwaggerConfig {
    @Bean
    public Docket docket(Environment environment) {


        boolean flag = environment.acceptsProfiles(Profiles.of("dev", "test"));
        System.out.println("flag:" + flag);

        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .groupName("cdp_operate")
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.xxx.web"))
                .build()
                .enable(flag);  // 是否开启Swagger
    }


    private ApiInfo apiInfo() {
        Contact contact = new Contact("LHH", "http://xxx.xxx.com/联系人访问链接", "lvhouhou@163.com");
        return new ApiInfo(
                "Demo Swagger", // 标题
                "Swagger API", // 描述
                "v1.0", // 版本
                "http://terms.service.url/组织链接", // 组织链接
                contact, // 联系人信息
                "Apach 2.0 许可", // 许可
                "许可链接", // 许可连接
                new ArrayList<>()// 扩展
        );
    }

    @Bean
    public Docket docket1(){
        return new Docket(DocumentationType.SWAGGER_2).groupName("group1");
    }
    @Bean
    public Docket docket2(){
        return new Docket(DocumentationType.SWAGGER_2).groupName("group2");
    }
    @Bean
    public Docket docket3(){
        return new Docket(DocumentationType.SWAGGER_2).groupName("group3");
    }
}

启动类

@SpringBootApplication
@MapperScan("com.xxx.dal")
@ServletComponentScan
@EnableWebMvc
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

MvcConfig

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MvcConfig implements WebMvcConfigurer {


    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/js/**").addResourceLocations("classpath:/js/");
        registry.addResourceHandler("/img/**").addResourceLocations("classpath:/img/");
        registry.addResourceHandler("/css/**").addResourceLocations("classpath:/css/");

        // 解决swagger无法访问
        registry.addResourceHandler("/swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
        // 解决swagger的js文件无法访问
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");

    }

}

拦截器配置


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


		// 注入拦截器
    @Autowired
    AuthenticationInterceptorConfig authenticationInterceptorConfig;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authenticationInterceptorConfig).addPathPatterns("/**")
                .excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**", "/error");
    }

}

拦截器

package xxx.interceptor;

import xxx.config.MAPIHttpServletRequestWrapper;
import xxx.dal.operation.dataobject.OperationAppDO;
import xxx.model.func.OperateUserDTO;
import xxx.model.func.UserHolder;
import xxx.service.OperationAppService;
import xxx.service.WhiteListService;
import xxx.util.ApplicationContextUtil;
import xxx.util.CusAccessObjectUtil;
import xxx.util.EncryptionUtil;
import org.apache.commons.net.util.SubnetUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.util.CollectionUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.*;

import static xxx.constant.InterceptorConstant.*;
import static xxx.model.error.OperationErrorEnum.ACCESS_EXPIRE;
import static xxx.model.error.OperationErrorEnum.ACCESS_PARAM_ERROR;

/**
 * ip白名单和API鉴权拦截器
 */


@Configuration
public class AuthenticationInterceptor extends HandlerInterceptorAdapter {

    private static final Logger logger = LoggerFactory.getLogger(AuthenticationInterceptor.class);

    private static WhiteListService whiteListService;

    private static OperationAppService operationAppService;

    private WhiteListService getWhitelistService() {
        if (Objects.isNull(whiteListService)){
            whiteListService = (WhiteListService)ApplicationContextUtil.getBean("whiteListServiceImpl");
        }
        return whiteListService;
    }
    private OperationAppService getOperationAppService() {
        if (Objects.isNull(operationAppService)){
            operationAppService = (OperationAppService)ApplicationContextUtil.getBean("operationAppServiceImpl");
        }
        return operationAppService;
    }


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        String methodName = method.getName();
        logger.info("==== AuthenticationInterceptor拦截器拦截到了方法:{},在该方法执行之前执行====", methodName);
        // 1、白名单
/*        String ipAddress = CusAccessObjectUtil.getIpAddress(request);
        List<String> allIp = getWhitelistService().getAllIp();

        boolean anyMatch = allIp.stream().anyMatch(ip -> new SubnetUtils(ip).getInfo().isInRange(ipAddress));

        if (!anyMatch){
            logger.info("==== AuthenticationInterceptor拦截器拦截到了方法:{}  白名单检验不通过  ====", methodName);
            return false;
        }*/
        // 2、校验header中的时间戳,时差不超过5分钟
        String timestamp = "";
        String sign = "";
        String appId = "";
        String userId = "";
        String name = "";
        try {
            timestamp = request.getHeader(TIMESTAMP);
            sign = request.getHeader(SIGN);
            appId = request.getHeader(APPID);
            userId = request.getHeader(EMP_ID);
            name = request.getHeader(NICK_NAME_CN);
            // TODO 需要还原
            if ((Math.abs(System.currentTimeMillis() - Long.valueOf(timestamp)) / 1000 / 60) > EXPIRE_TIME) {
                response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
                response.getOutputStream().write(new String(ACCESS_EXPIRE.getErrorDesc()).getBytes(StandardCharsets.UTF_8));
                logger.info("==== AuthenticationInterceptor拦截器拦截到了方法:{} 时间戳过期  ====", methodName);
                return false;
            }
            OperateUserDTO user = new OperateUserDTO();
            user.setId(userId);
            user.setNickName(name);
            UserHolder.saveUser(user);
           
        } catch (Exception e) {
            response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            response.getOutputStream().write(new String(ACCESS_PARAM_ERROR.getErrorDesc()).getBytes(StandardCharsets.UTF_8));
            logger.info("==== AuthenticationInterceptor拦截器拦截到了方法:{} 解析鉴权参数异常  ====", methodName);
            return false;
        }


        // 3、校验参数
        Map<String, OperationAppDO> operationAppDOMap = getOperationAppService().getAllAppInfo();
        if (!operationAppDOMap.containsKey(appId)){
            logger.info("==== AuthenticationInterceptor拦截器拦截到了方法:{} 鉴权失败 appId不存在  ====", methodName);
            return false;
        }
        //MAPIHttpServletRequestWrapper解决流不能读两次的问题
        Map<String,Object> paramMap = MAPIHttpServletRequestWrapper.getBodyMap(request.getInputStream());

       
        List<String> paramList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(paramMap)){
            for (String s : paramMap.keySet()) {
                paramList.add(paramMap.get(s).toString());
            }
        }
        paramList.add(appId);
        paramList.add(timestamp);
        paramList.add(operationAppDOMap.get(appId).getAppSecret());
        Collections.sort(paramList, String::compareTo);
        StringBuilder builder = new StringBuilder();
        paramList.forEach(param -> builder.append(param));
        String md5 = EncryptionUtil.getMD5(builder.toString());
        if (Objects.equals(md5, sign)){
            return true;
        }
        logger.info("==== AuthenticationInterceptor拦截器拦截到了方法:{} 鉴权失败 签名鉴权失败  ====", methodName);
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        logger.info("AuthenticationInterceptor 执行完方法之后进执行(Controller方法调用之后),但是此时还没进行视图渲染");
        super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        logger.info("AuthenticationInterceptor 整个请求都处理完咯,DispatcherServlet也渲染了对应的视图咯");
        super.afterCompletion(request, response, handler, ex);
    }


}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值