Swagger


Swagger 官方文档

使用第三方工具包

增加包版本


<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>swagger-bootstrap-ui</artifactId>
    <version>${swagger-bootstrap-ui.version}</version>
</dependency>

删除原来swagger-ui包


<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>${springfox-swagger2.version}</version>
</dependency>

配置类加上注解 @EnableSwaggerBootstrapUI

yml配置登录名密码

# swagger配置
swagger:
  production: false
  basic:
    enable: true
    username: cplh_swagger
    password: ************

swagger关闭ui放行

// filterChainDefinitionMap.put("/swagger-ui.html", ANON);

swagger地址由原来的 /swagger-ui.html 变更为 /doc.html

cloud升级方法

  • cloud每个服务都应当升级swagger访问加密
  • 网关需要放行对应的资源与请求

自定义简单校验(基于http安全协议)

  • 通过拦截器自定义拦截逻辑

@Slf4j
@WebFilter(urlPatterns = {"/swagger*", "/swagger/*", "/swagger-resources/*", "/v3/*"}, filterName = "swaggerSecurityFilter")
public class SwaggerSecurityFilter implements Filter {
    public static final String SWAGGER_SECURITY_SESSION = "swaggerSecuritySession";
    @Value("${system-config.swagger-security:true}")
    private boolean security = true;
    @Value("${system-config.swagger-username:cplh_swagger}")
    private String username;
    @Value("${system-config.swagger-password:ZHbootvue@swagger}")
    private String password;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest servletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        if (this.security) {
            String swaggerSessionValue = (String) servletRequest.getSession().getAttribute(SWAGGER_SECURITY_SESSION);
            if (StringUtils.isNotBlank(swaggerSessionValue) && StringUtils.equals(swaggerSessionValue, this.username)) {
                // 如果session中有值且等于密码, 取消拦截
                chain.doFilter(request, response);
            } else {
                String auth = servletRequest.getHeader("Authorization");
                if (StringUtils.isNotBlank(auth)) {
                    String userAndPass = new String(Base64.getDecoder().decode(auth.substring(6)));
                    String[] upArr = userAndPass.split(":");
                    if (upArr.length != 2) {
                        this.writeForbiddenCode(httpServletResponse);
                        return;
                    }

                    String iptUser = upArr[0];
                    String iptPass = upArr[1];
                    if (StringUtils.isNotBlank(iptUser) && StringUtils.isNotBlank(iptPass)
                            && StringUtils.equals(iptUser, this.username) && StringUtils.equals(iptPass, this.password)) {
                        servletRequest.getSession().setAttribute(SWAGGER_SECURITY_SESSION, this.username);
                        chain.doFilter(request, response);
                        return;
                    }

                    this.writeForbiddenCode(httpServletResponse);
                    return;
                }
                this.writeForbiddenCode(httpServletResponse);
            }
        } else {
            chain.doFilter(request, response);
        }
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }

    private void writeForbiddenCode(HttpServletResponse httpServletResponse) throws IOException {
        httpServletResponse.setStatus(HttpStatus.SC_UNAUTHORIZED);
        httpServletResponse.setHeader(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"input Swagger Basic userName & password \"");
        httpServletResponse.getWriter().write("You do not have permission to access this resource");
    }
}
  • 增加请求头需要的通用参数

@Configuration
@EnableOpenApi
@ConditionalOnProperty(prefix = SystemConfig.PREFIX, name = "swagger-open", havingValue = "true")
public class Swagger2Config implements WebMvcConfigurer {
    @Bean
    public Docket createRestApi(SystemConfig systemConfig) {
        //添加head参数配置start
        List<RequestParameter> pars = new ArrayList<>();
        pars.add(new RequestParameterBuilder().in(ParameterType.HEADER).required(false)
                .name(CommonConstant.ACCESS_TOKEN).description(CommonConstant.ACCESS_TOKEN).build());
        pars.add(new RequestParameterBuilder().in(ParameterType.HEADER).required(false)
                .name(SysClientConfigUtils.CLIENT_ID).description(SysClientConfigUtils.CLIENT_ID).build());
        pars.add(new RequestParameterBuilder().in(ParameterType.HEADER).required(false)
                .name(SysClientConfigUtils.CLIENT_SECRET).description(SysClientConfigUtils.CLIENT_SECRET).build());
        return new Docket(DocumentationType.OAS_30)
                .apiInfo(apiInfo(systemConfig))
                .select()
                //加了ApiOperation注解的类,才生成接口文档
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(PathSelectors.any())
                .build()
                .globalRequestParameters(pars);
    }

    private ApiInfo apiInfo(SystemConfig systemConfig) {
        return new ApiInfoBuilder()
                //大标题
                .title("zh-boot 接口平台")
                //描述
                .description("zh-boot 接口平台")
                //版本号
                .version(systemConfig.getVersion())
                .build();
    }
}

文章作者: 艾茜茜
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 艾茜茜 !
  目录