有不少文章提到,在生产环境中须要关闭Swagger功能,防止系统资源泄露。今天,我结合本身开发过程当中的经验,分享一个只需几行代码即可实现让Apache Shiro接管Swagger认证和受权的方法。若是还有更好的方法,欢迎在文章末尾给我留言,一块儿交流。html
简单来讲,Swagger是一个开放源代码的框架,旨在使用通用化的语言,让开发者和非开发者都能理解你设计的API是什么结构,有什么用途。API文档比如建筑蓝图,在建造房子时,必须按照蓝图的规格参数进行。
一般,一个软件项目会伴随着不少的API文档须要编写,当软件版本变动时,还须要修改全部的API文档细节(例如:请求地址,请求参数,返回值等等)。这是一件极具挑战性的工做。长期以来,工程师们一直在努力寻找一种标准化的流程/方法来解决API文档的设计,编写,测试和维护问题,Swagger就是在这样一种背景下诞生的。java
Swagger为API文档的设计,开发,测试,维护提供了统一的解决方案。这极大的减轻了开发人员的工做负担。但随之而来的一个问题也会让人担忧,经过Swagger UI提供统一的API文档阅览和测试,这会致使在生产环境下暴露系统资源。spring
咱们并不但愿全部人均可以查阅系统的API文档,就像不是全部人都有权限查看建筑蓝图同样。那么如何解决这一问题呢?apache
Swagger官方提供了6种认证和受权方式:basic-authentication、API密钥、bearer-authentication、Oauth 2.0、OpenID Connect Discovery和Cookie。但这几种方式在体验上效果都很差(固然,你也能够选择在生产环境中关闭Swagger的功能)。能不能有一种方式,让系统自己的权限认证体系接管Swagger的受权认证工做,让Swagger专一于本身擅长的领域呢?这就是本文要介绍的重点。api
Apache Shiro™是一个功能强大且易于使用的Java安全框架,用于执行身份认证,受权,加密和会话管理。你能够轻松地将其集成到你的项目中,且不须要改动太多的代码。Shiro支持一个或多个可插拔的数据源,例如LDAP、JDBC、Active Directory等等,与此同时,Shiro还支持不一样粒度的访问控制,如基于用户组,用户角色,资源权限等。缓存
首先,假定你已经在本身的项目中使用了Swagger,而且你的项目是基于Spring Boot 2.0进行构建的,同时使用Maven对项目的依赖进行管理。若是你的项目还未使用Swagger,请将下面代码配置到pom.xml文件中:安全
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency>
另外,请检查项目中是否加入了Shiro项目依赖,若是还未添加,请将下面代码配置到pom.xml文件中:app
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.4.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>1.4.0</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency>
备注shiro-core:Apache Shiro核心依赖包框架
shiro-ehcache:基于Ehcache实现的数据缓存依赖包测试
shiro-spring:Apache Shiro与Spring整合依赖包
依赖就绪后,建立一个Swagger的配置文件并设置Swagger要扫描的包路径(一般是Controller所在的包),API文档标题(title),描述(description),版本号(version),联系方式(contact)以及证书名称(license)等等。下面是Swagger配置文件示例:
SwaggerConfiguration.java
@Configuration @EnableSwagger2 public class SwaggerConfiguration { @Bean public Docket createRestApi(){ return new Docket(DocumentationType.SWAGGER_2) .pathMapping("/") .select() .apis(RequestHandlerSelectors.basePackage("com.ramostear.controller")) .paths(PathSelectors.any()) .build() .apiInfo( new ApiInfoBuilder() .title("Apache Shiro & Swagger") .description("使用Apache Shiro接管Swagger认证和受权") .version("1.0.0") .contact( new Contact("树下魅狐", "https://www.ramostear.com", "ramostear@163.com") ) .license("The Apache License") .build() ); } }
注意除了使用@Configuration对配置类进行注解外,别将@EnableSwagger注解遗漏!
若是你的项目已经使用Apache Shiro进行认证和受权工做,那么只须要在ShiroFilterFactoryBean的配置代码中加入对Swagger的过滤操做便可。你能够参照下面的代码进行配置:
ShiroConfiguration.java
@Configuration public class ShiroConfiguration{ @Bean public EhCacheManager ehCacheManager(){...} @Bean public CustomShiroRealm customShiroRealm(){...} @Bean public SecurityManager securityManager(){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setCacheManager(ehCacheManager()); securityManager.setRealm(customShiroRealm()); return securityManager; } ... @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){ ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean(); filterFactoryBean.setSecurityManager(securityManager); Map<String,String> filterChainDefinition = new LinkedHashMap<>(); ... filterChainDefinition.put("/swagger-ui.html","authc"); filterChainDefinition.put("/v2/**","authc"); filterChainDefinition.put("/swagger-resources/**","authc"); filterFactoryBean.setFilterChainDefinitionMap(filterChainDefinition); return filterFactoryBean; } .... }
补充除了上述给出的配置方式外,你能够根据实际须要,配置更细粒度的权限,例如用户组,角色以及资源权限等等。
至此,若是你的项目本来使用了Apache Shiro框架,那么只需在原代码的基础上,增长三行配置代码,便可让Apache Shiro接管Swagger的认证和受权工做。
最后,经过实际项目来演示Apache Shiro接管Swagger认证和受权工做的效果:
说明
/admin/swagger请求页面嵌入了一个iframe,其地址为:/swagger-ui.html。具体代码以下:
swagger.html
<html> <head> ... </head> <body> ... <iframe src="./swagger-ui.html" frameborder="0" scrolling="auto"></iframe> ... </body> </html>
当用户登陆成功后,能够正常访问Swagger的API文档页面,当注销当前用户后,再次访问Swagger页面,系统会跳转到用户登陆页面,要求验证用户身份。