Swagger ui登录功能实现方案

 

1. Swagger ui登录功能实现方案

https://www.cnblogs.com/zeng1994/p/c08f48f27ddfcf71950a9c1fac80fade.html

2. swagger登录进行用户名和密码认证

https://www.jianshu.com/p/0b956fac8780?u_atoken=03a390bf-2aea-40fe-a33d-db1cc1e7164f&u_asession=01R4XvBRRHggPztZwoDQBtI9-5D31RHz-Z75oULkcuAw-frdmro63SPiFKQg4Fp0KKX0KNBwm7Lovlpxjd_P_q4JsKWYrT3W_NKPr8w6oU7K91xfzieAwCWUiEUZshBdqLkC1LUOsbnJoxzzl_EpVkQGBkFo3NEHBv0PZUm6pbxQU&u_asig=054B9JWP5MZltLpP-wXKfhETDWfuM6MbhOL0TUXcQ1iIbGs0jmdLqk3QSUDfCMFXLVX_KmDpyVHKY2rw3Dt6uR5lSsNkYWys-BLvH6pxv9OzEw-5BLRGlQfUzy6kp-EVQ-PVUW7WvHYC8CvEvDDo9Zn88fjL6RfLW_dQBEp5dBCdz9JS7q8ZD7Xtz2Ly-b0kmuyAKRFSVJkkdwVUnyHAIJzTtPK213qNeaLLJyzkcBJ4J6EzMlVlc7miH6rSFAaKXEUDrMH9U5oL9icxwFsJSlo-3h9VXwMyh6PgyDIVSG1W_AIVf4Y0YcswSrj33IBDEHH7tx7E3bKmsnQi7JCMY423__BY6tcVUBDaV75qW_xAnVMAeiP95edQYvlUjIuvIymWspDxyAEEo4kbsryBKb9Q&u_aref=7EsuavKclNEiLSTgZLu%2FhvF5etE%3D

 

_____________________________________________________________________________________________________________________________________________________________________

在项目开发过程中,swagger ui是个非常好用的在线接口文档生成工具。但他有个缺点,不够安全,可以直接访问。虽然生产环境一般会关闭它,但难免有时候有人会把它开启,所以它需要一个登录的功能。本文将叙述登录功能的两种实现方案,两种方案随便一种都可以使用,看个人喜好。

一、环境说明

    springboot 版本 2.2.10
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.10.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    swagger-ui版本 2.9.2
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>

二、方案一

    使用第三方组件swagger-bootstrap-ui 提供的登录功能

(1)引依赖

    pom文件中引入如下依赖
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>swagger-bootstrap-ui</artifactId>
            <version>1.9.6</version>
        </dependency>

(2)启用配置

    在swagger的配置类中,添加@EnableSwaggerBootstrapUI注解,参考下图
        

(3)配置账号密码

    application.yml中配置账号密码
swagger:
  basic:
    # 开启身份认证功能
    enable: true
    username: root
    password: 123456

(4)原理说明

    原理很简单,参考下面两个类
com.github.xiaoymin.swaggerbootstrapui.filter.SecurityBasicAuthFilter----这个核心实现类
com.github.xiaoymin.swaggerbootstrapui.configuration.SecurityConfiguration----配置类
 

三、方案二

    自己利用SpringSecurity来的Basic认证来实现登录功能

(1)实现代码

    swagger配置类
package com.zxy.original.admin.config;

import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger.web.UiConfiguration;
import springfox.documentation.swagger.web.UiConfigurationBuilder;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * swagger文档配置
 * @date 2021-06-23
 */
@Profile("dev")
@Configuration
@EnableSwagger2
public class SwaggerConfig {

    /**
     * 添加摘要信息(Docket)
     */
    @Bean
    public Docket controllerApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(new ApiInfoBuilder()
                        .title("管理后台文档")
                        .description("管理后台-接口文档")
                        .contact(new Contact("youname", null, "wwww@swagger.com.cn"))
                        .version("V1.3")
                        .build())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.zxy.original.admin.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    @Bean
    public UiConfiguration uiConfiguration() {
        return UiConfigurationBuilder.builder().defaultModelsExpandDepth(0).build();
    }



    /******************************************下面为使用SpringSecurity扩展的swagger ui的登录认证功能 **************************************************/

    /**
     * swagger ui 登录功能配置类,依赖了SpringSecurity,
     * <br/>下面一定要添加@Order注解,解决项目中有多个SpringSecurity配置类时配置优先级问题
     * @author ZENG.XIAO.YAN
     * @Date 2021-06-23
     * @version 1.0
     */
    @Configuration
    @ConditionalOnProperty(name = "swagger.config.login", havingValue = "true")
    @EnableConfigurationProperties(value = SwaggerConfig.SwaggerConfigBeanProperties.class)
    @Order(1)
    @Slf4j
    public static class SwaggerSecurityConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        private SwaggerConfigBeanProperties swaggerConfigBeanProperties;

        public SwaggerSecurityConfig() {
            log.error("^_^----------------启用了Swagger ui 的身份认证功能,需要登录后才能访问---------------^_^");
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {

            //  这个配置只针对 swagger-ui 相关请求
            http.requestMatchers()
                    .antMatchers("/swagger-resources/**",
                            "/webjars/**", "/v2/**", "/swagger-ui.html/**",  "/doc.html/**")
                    .and()
                    // swaggerui 下所有请求都要认证
                    .authorizeRequests().anyRequest().authenticated()
                    // 启用httpBasic认证模式
                    .and().httpBasic()
                    // 禁用csrf
                    .and().csrf().disable();
        }

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            auth.inMemoryAuthentication()
                    .passwordEncoder(new BCryptPasswordEncoder())
                    .withUser(swaggerConfigBeanProperties.getUsername())
                    .password(passwordEncoder.encode(swaggerConfigBeanProperties.getPassword()))
                    .roles("admin");
        }
    }


    /**
     * swagger ui 的一些配置,这里不加@Configuration,在上面用@EnableConfigurationProperties来启用
     * @author ZENG.XIAO.YAN
     * @Date 2021-06-23
     * @version 1.0
     */
    @ConfigurationProperties(prefix = "swagger.config")
    @Data
    public static class SwaggerConfigBeanProperties {
        /** swagger 用户名,默认值swagger */
        private String username = "swagger";
        /** swagger密码,默认值123456 */
        private String password = "123456";
        /** 启用身份认证功能 */
        private boolean login;
    }
}
 
    application.yml中配置登录的账号密码等信息
# swagger 登录认证功能
swagger:
  config:
    login: true
    username: root
    password: 123456
YAML 复制 全屏
 

(2)注意事项

  • 需要引入SpringSecurity的依赖
  • 如果项目中已经使用了SpringSecurity,那么需要保证Swagger里面的SpringSecurity的配置类的优先级更高

四、小结

  • 两种实现方案,如果项目中用了swagger-bootstrap-ui ,那么肯定用方案一
  • 如果不想引入swagger-bootstrap-ui ,那么就用方案二

 

 

_____________________________________________________________________________________________________________________________________________________________________

 

swagger登录进行用户名和密码认证 

因安全检查,需要对swagger-ui登录需要用户名密码登录

1、添加依赖

     <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>swagger-bootstrap-ui</artifactId>
            <version>1.9.6</version>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>

2、添加拦截器

import cn.evun.sweet.framework.common.util.AntPathMatcher;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import sun.misc.BASE64Decoder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class SwaggerInterceptor extends HandlerInterceptorAdapter {
    private String username;
    private String password;
    public SwaggerInterceptor(String username, String password) {
        this.username = username;
        this.password = password;
    }
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String authorization = request.getHeader("Authorization");
        boolean isAuthSuccess = httpBasicAuth(authorization);
        if (!isAuthSuccess) {
            response.setCharacterEncoding("utf-8");
            response.setStatus(401);
//            response.setStatus(401,"Unauthorized");
            response.setHeader("WWW-authenticate", "Basic realm=\"Realm\"");
            try (PrintWriter writer = response.getWriter()) {
                writer.print("Forbidden, unauthorized user");
            }
        }
        return isAuthSuccess;
    }
    public boolean httpBasicAuth(String authorization) throws IOException {
        if (authorization != null && authorization.split(" ").length == 2) {
            String userAndPass = new String(new BASE64Decoder().decodeBuffer(authorization.split(" ")[1]));
            String username = userAndPass.split(":").length == 2 ? userAndPass.split(":")[0] : null;
            String password = userAndPass.split(":").length == 2 ? userAndPass.split(":")[1] : null;
            if (this.username.equals(username) && this.password.equals(password)) {
                return true;
            }
        }
        return false;
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        String uri = request.getRequestURI();
        AntPathMatcher pathMatcher = new AntPathMatcher();
        if (!pathMatcher.match("/swagger-ui.html", uri) && !pathMatcher.match("/webjars/**", uri)) {
            response.setStatus(404);
            return;
        }
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource[] resources = resolver.getResources("classpath:/META-INF/resources" + uri);
        if (resources != null && resources.length > 0) {
            FileCopyUtils.copy(resources[0].getInputStream(), response.getOutputStream());
        } else {
            response.setStatus(404);
        }
    }

}

4、添加配置类

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.handler.MappedInterceptor;


@Configuration
public class SwaggerConfig {
    @Value("${swagger.basic.username:admin}")
    private String username;
    @Value("${swagger.basic.password:admin}")
    private String password;

    /* 必须在此处配置拦截器,要不然拦不到swagger的静态资源 */
    @Bean
    @ConditionalOnProperty(name = "swagger.basic.enable", havingValue = "true")
    public MappedInterceptor getMappedInterceptor() {
        return new MappedInterceptor(new String[]{"/swagger-ui.html", "/webjars/**"},
                new SwaggerInterceptor(username, password));
    }

}

5、添加配置

swagger.basic.enable=true
swagger.basic.username=admin
swagger.basic.password=admin
 
 
 

 

posted @ 2022-09-27 17:54  kelelipeng  阅读(2298)  评论(0编辑  收藏  举报