Swagger權限認證上:基於Apache Shiro

有不少文章提到,在生產環境中須要關閉Swagger功能,防止系統資源泄露。今天,我結合本身開發過程當中的經驗,分享一個只需幾行代碼即可實現讓Apache Shiro接管Swagger認證和受權的方法。若是還有更好的方法,歡迎在文章末尾給我留言,一塊兒交流。html

初識Swagger

簡單來講,Swagger是一個開放源代碼的框架,旨在使用通用化的語言,讓開發者和非開發者都能理解你設計的API是什麼結構,有什麼用途。API文檔比如建築藍圖,在建造房子時,必須按照藍圖的規格參數進行。

一般,一個軟件項目會伴隨着不少的API文檔須要編寫,當軟件版本變動時,還須要修改全部的API文檔細節(例如:請求地址,請求參數,返回值等等)。這是一件極具挑戰性的工做。長期以來,工程師們一直在努力尋找一種標準化的流程/方法來解決API文檔的設計,編寫,測試和維護問題,Swagger就是在這樣一種背景下誕生的。
imagejava

Swagger爲API文檔的設計,開發,測試,維護提供了統一的解決方案。這極大的減輕了開發人員的工做負擔。但隨之而來的一個問題也會讓人擔憂,經過Swagger UI提供統一的API文檔閱覽和測試,這會致使在生產環境下暴露系統資源。spring

咱們並不但願全部人均可以查閱系統的API文檔,就像不是全部人都有權限查看建築藍圖同樣。那麼如何解決這一問題呢?apache

Apache Shiro接管Swagger權限認證

Swagger官方提供了6種認證和受權方式:basic-authenticationAPI密鑰bearer-authenticationOauth 2.0OpenID Connect DiscoveryCookie。但這幾種方式在體驗上效果都很差(固然,你也能夠選擇在生產環境中關閉Swagger的功能)。能不能有一種方式,讓系統自己的權限認證體系接管Swagger的受權認證工做,讓Swagger專一於本身擅長的領域呢?這就是本文要介紹的重點。api

快速認識Apache Shiro

Apache Shiro™是一個功能強大且易於使用的Java安全框架,用於執行身份認證,受權,加密和會話管理。你能夠輕鬆地將其集成到你的項目中,且不須要改動太多的代碼。Shiro支持一個或多個可插拔的數據源,例如LDAP、JDBC、Active Directory等等,與此同時,Shiro還支持不一樣粒度的訪問控制,如基於用戶組,用戶角色,資源權限等。
image緩存

使用Shiro接管Swagger認證受權

首先,假定你已經在本身的項目中使用了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整合依賴包
image

配置Swagger

依賴就緒後,建立一個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註解遺漏!

在Shiro中配置Swagger

若是你的項目已經使用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頁面,系統會跳轉到用戶登陸頁面,要求驗證用戶身份。


image

相關文章
相關標籤/搜索