spring boot:swagger3的安全配置(swagger 3.0.0 / spring security / spring boot 2.3.3)

一,swagger有哪些环节需要注意安全?

1,生产环境中,要关闭swagger

   application.properties中配置:

  springfox.documentation.swagger-ui.enabled=false

2,swagger使用一台专用的服务器来部署,

   可以访问的ip地址要做限制,

   外部的防火墙和应用中都做限制,

3,自定义访问swagger的url

 4, 可以访问swagger的用户要做权限的验证

说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest

         对应的源码可以访问这里获取: https://github.com/liuhongdi/

说明:作者:刘宏缔 邮箱: 371125307@qq.com

二,演示项目的相关信息

1,项目地址

https://github.com/liuhongdi/swagger3security

2,项目功能说明:

     演示了swagger3的安全配置

3,项目结构:如图:

spring boot:swagger3的安全配置(swagger 3.0.0 / spring security / spring boot 2.3.3)

三,配置文件说明

1,pom.xml

        <!-- swagger3 begin -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
            <version>3.0.0</version>
        </dependency>
        <!-- spring security -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

2,application.properties

#error
server.error.include-stacktrace=always
#error
logging.level.org.springframework.web=trace
#swagger,使可用
springfox.documentation.swagger-ui.enabled=true
#改变url
springfox.documentation.swagger-ui.base-url=/lhddoc
#设置允许访问的ip地址白名单
swagger.access.iplist = 192.168.3.1,127.0.0.1

四,java代码说明

1,Swagger3Config.java

@EnableOpenApi
@Configuration
public class Swagger3Config implements WebMvcConfigurer {

    @Bean
    public Docket createRestApi() {
        //返回文档摘要信息
        return new Docket(DocumentationType.OAS_30)
                .apiInfo(apiInfo())
                .select()
                //.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .apis(RequestHandlerSelectors.withMethodAnnotation(Operation.class))
                .paths(PathSelectors.any())
                .build()
                .globalRequestParameters(getGlobalRequestParameters())
                .globalResponses(HttpMethod.GET, getGlobalResonseMessage())
                .globalResponses(HttpMethod.POST, getGlobalResonseMessage());
    }

    //生成接口信息,包括标题、联系人等
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Swagger3接口文档")
                .description("如有疑问,请联系开发工程师老刘。")
                .contact(new Contact("刘宏缔", "https://www.cnblogs.com/architectforest/", "371125307@qq.com"))
                .version("1.0")
                .build();
    }

    //生成全局通用参数
    private List<RequestParameter> getGlobalRequestParameters() {
        List<RequestParameter> parameters = new ArrayList<>();
        parameters.add(new RequestParameterBuilder()
                .name("appid")
                .description("平台id")
                .required(true)
                .in(ParameterType.QUERY)
                .query(q -> q.model(m -> m.scalarModel(ScalarType.STRING)))
                .required(false)
                .build());
        parameters.add(new RequestParameterBuilder()
                .name("udid")
                .description("设备的唯一id")
                .required(true)
                .in(ParameterType.QUERY)
                .query(q -> q.model(m -> m.scalarModel(ScalarType.STRING)))
                .required(false)
                .build());
        parameters.add(new RequestParameterBuilder()
                .name("version")
                .description("客户端的版本号")
                .required(true)
                .in(ParameterType.QUERY)
                .query(q -> q.model(m -> m.scalarModel(ScalarType.STRING)))
                .required(false)
                .build());
         return parameters;
    }

    //生成通用响应信息
    private List<Response> getGlobalResonseMessage() {
        List<Response> responseList = new ArrayList<>();
        responseList.add(new ResponseBuilder().code("404").description("找不到资源").build());
         return responseList;
    }
}

配置swagger3

2,HomeController.java

@Api(tags = "首页信息管理")
@Controller
@RequestMapping("/home")
public class HomeController {

    @Operation(summary = "session详情")
    @GetMapping("/session")
    @ResponseBody
    public String session() {
        HttpSession session = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getSession();
        Enumeration e   =   session.getAttributeNames();
        String s = "";
        while( e.hasMoreElements())   {
            String sessionName=(String)e.nextElement();
            s += "name="+sessionName+";<br/>";
            s += "value="+session.getAttribute(sessionName)+";";
        }
        return s;
    }

}

查看当前登录用户的session

3,SecurityConfig.java

@Configuration
@EnableWebSecurity
 public class SecurityConfig extends WebSecurityConfigurerAdapter {

     @Value("${swagger.access.iplist}")
     private String iplist;

     @Override
     protected void configure(HttpSecurity http) throws Exception {
                 //得到iplist列表
                String iprule = "";
                //hasIpAddress('10.0.0.0/16') or hasIpAddress('127.0.0.1/32')
                String[] splitAddress=iplist.split(",");
                for(String ip : splitAddress){
                     if (iprule.equals("")) {
                         iprule = "hasIpAddress('"+ip+"')";
                     } else {
                         iprule += " or hasIpAddress('"+ip+"')";
                     }
                }
                String swaggerrule = "hasAnyRole('ADMIN','DEV') and ("+iprule+")";

                  //login和logout
                  http.formLogin()
                         .defaultSuccessUrl("/home/session")
                        .failureUrl("/login-error.html")
                        .permitAll()
                       .and()
                       .logout();

                  //匹配的页面,符合限制才可访问
                  http.authorizeRequests()
                  //.antMatchers("/actuator/**").hasIpAddress("127.0.0.1")
                  //.antMatchers("/admin/**").access("hasRole('admin') and (hasIpAddress('127.0.0.1') or 
//hasIpAddress('192.168.1.0/24') or hasIpAddress('0:0:0:0:0:0:0:1'))");
.antMatchers("/lhddoc/**").access(swaggerrule) .antMatchers("/goods/**").hasAnyRole("ADMIN","DEV"); //剩下的页面,允许访问 http.authorizeRequests().anyRequest().permitAll(); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { //添加两个账号用来做测试 auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()) .withUser("lhdadmin") .password(new BCryptPasswordEncoder().encode("123456")) .roles("ADMIN","USER") .and() .withUser("lhduser") .password(new BCryptPasswordEncoder().encode("123456")) .roles("USER"); } }

spring security的配置,重点是ip地址白名单的限制要加入

4,Goods.java等,可以从github.com查看

五,测试效果

1,无权限的访问效果:

spring boot:swagger3的安全配置(swagger 3.0.0 / spring security / spring boot 2.3.3)

 用lhduser账号登录

从session页面可以看到当前登录用户的授权角色是:ROLE_USER

spring boot:swagger3的安全配置(swagger 3.0.0 / spring security / spring boot 2.3.3)

 因为没有权限,访问swagger时会报错

spring boot:swagger3的安全配置(swagger 3.0.0 / spring security / spring boot 2.3.3)

2,有权限访问时的效果:

用lhdadmin登录

spring boot:swagger3的安全配置(swagger 3.0.0 / spring security / spring boot 2.3.3)

 查看session:

spring boot:swagger3的安全配置(swagger 3.0.0 / spring security / spring boot 2.3.3)

 可以看到用户权限包括:ROLE_ADMIN

访问swagger:

http://127.0.0.1:8080/lhddoc/swagger-ui/

返回:

spring boot:swagger3的安全配置(swagger 3.0.0 / spring security / spring boot 2.3.3)

3,从非授权的ip地址访问:

既使用获得授权的用户账号登录也会报错,因为ip未授权

spring boot:swagger3的安全配置(swagger 3.0.0 / spring security / spring boot 2.3.3)

六,查看spring boot的版本

  .   ____          _            __ _ _
 /\ / ___'_ __ _ _(_)_ __  __ _    
( ( )\___ | '_ | '_| | '_ / _` |    
 \/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.3.RELEASE)