有不少文章提到,在生產環境中須要關閉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頁面,系統會跳轉到用戶登陸頁面,要求驗證用戶身份。