SpringBoot:整合Shiro之攔截器配置

前言
前面的幾篇部落格都是說的使用者如何認證,如何授權,那麼使用者認證授權之後,我們該如何使用這些資訊呢?這裡我們就需要使用到Shiro框架中的攔截器功能.通過攔截器功能實現使用者許可權和角色的應用,下面我們就來看一下我們如何使用攔截器實現使用者許可權認證的應用.
攔截器分類說明
在配置攔截器之前,我們需要先了解Shiro本身給我們提供的攔截器都有什麼,都有著什麼樣的特點.下面我們就來用表格的形式來看一下各種攔截器的特點.
簡寫(加粗為常用) | 名稱 | 優先順序(1為最高) | 說明 | 對應Java類 |
---|---|---|---|---|
anon | 匿名攔截器 | 1 | 不需要登入就能訪問,一般用於靜態資源,或者移動端介面 | org.apache.shiro.web.filter.authc.AnonymousFilter |
authc | 登入攔截器 | 2 | 需要登入認證才能訪問的資源 | org.apache.shiro.web.filter.authc.FormAuthenticationFilter |
authcBasic | Http攔截器 | 3 | Http身份驗證攔截器,非常用型別,不太瞭解 | org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter |
logout | 登出攔截器 | 4 | 使用者登出攔截器,主要屬性: redirectURL 退出登入後重定向的地址 | org.apache.shiro.web.filter.authc.LogoutFilter |
noSessionCreation | 不建立會話攔截器 | 5 | 呼叫 subject.getSession(false) 不會有什麼問題,但是如果 subject.getSession(true) 將丟擲 DisabledSessionException 異常 | org.apache.shiro.web.filter.authc.NoSessionCreationFilter |
prems | 許可權攔截器 | 6 | 驗證使用者是否擁有資源許可權 | org.apache.shiro.web.filter.authc.PermissionsAuthorizationFilter |
port | 埠攔截器 | 7 | 其主要屬性: port(80) 如果使用者訪問該頁面是非 80,將自動將請求埠改為 80 並重定向到該 80 埠 | org.apache.shiro.web.filter.authc.PortFilter |
rest | rest風格攔截器 | 8 | rest 風格攔截器,自動根據請求方法構建許可權字串構建許可權字串;非常用型別攔截器 | org.apache.shiro.web.filter.authc.HttpMethodPermissionFilter |
roles | 角色攔截器 | 9 | 驗證使用者是否擁有資源角色 | org.apache.shiro.web.filter.authc.RolesAuthorizationFilter |
ssl | SSL攔截器 | 10 | 只有請求協議是https才能通過,否則你會自動跳轉到https埠(443) | org.apache.shiro.web.filter.authc.SslFilter |
user | 使用者攔截器 | 11 | 使用者攔截器,使用者已經身份驗證 / 記住我登入的都可; | org.apache.shiro.web.filter.authc.UserFilter |
我們通過上面的表格可以輕鬆的分別每一種攔截器的優先順序,這樣假設某個資源訪問同時設定了兩個或者多個攔截器,我們可以清楚的知道攔截器的執行順序,從而方便我們進行一些操作.
INI檔案配置攔截器
我曾經在 ofollow,noindex">SpringBoot:整合Shiro之INI配置篇 說過 [urls]模組 .但是,說的不是太詳細.在這個模組,我們就來詳細的看一下如何使用 INI 檔案的形式配置過濾器.
在配置之前,我們還需要重述一下 攔截器的萬用字元的寫法,如下所示.
?:匹配一個字元 *:匹配零個或多個字元 **:匹配零個或多個路徑
然後,我們看一下[urls]模組的示例.這裡我只用到了一些常用的攔截器
[urls] #不需要登入 /login=anon /static/**=anon #需要登入 /home=authc #需要角色 /deleteUser = roles["superAdmin"] #需要使用者許可權 /addUser = perms["user:create"]
但是,我們發現一個問題,假設使用者沒有該許可權和沒有該角色,或者沒有登入的時候,還有登出的時候,我們都需要給他們配置對應的重定向路徑.這時候,我們就不能在 [urls] 模組中使用了,我們需要在 [main] 模組中進行各個情況路徑的重定向設定了.示例程式碼如下所示.
[main] #使用者登入的地址 authc.loginUrl = /login #使用者沒有對應角色的跳轉重指向 roles.unauthorizedUrl = /login #使用者沒有對應許可權的跳轉重指向 perms.unauthorizedUrl = /login #使用者登出的跳轉重指向 logout.redirectUrl = /login
注意:INI檔案中 [urls] 模組攔截順序是從上往下依次執行.
程式碼形式配置攔截器
使用INI檔案配置攔截器是較為簡潔的配置形式,其實質就是通過Bean注入的形式配置攔截器 接下來我們看一下我們如何通過程式碼形式配置攔截器.
由於是使用的 SpringBoot:整合Shiro之自定義Realm實現認證授權 專案中的程式碼配置,那麼,我們就看一下上一節都配置了什麼吧,我們配置了核心安全事務管理器 和自定義的許可權登入器.程式碼如下所示.
@Configuration public class ShiroConfiguration { //配置核心安全事務管理器 @Bean(name="securityManager") public DefaultWebSecurityManager securityManager(@Qualifier("myShiroRealm") MyShiroRealm myShiroRealm) { DefaultWebSecurityManager manager=new DefaultWebSecurityManager(); manager.setRealm(myShiroRealm); return manager; } //配置自定義的許可權登入器 @Bean(name="myShiroRealm") public MyRealm authRealm() { MyRealm myShiroRealm=new MyRealm(); return myShiroRealm; } }
我們繼續配置攔截器模組的程式碼.整體程式碼如下所示.
@Bean(name="shiroFilter") public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") DefaultWebSecurityManager manager) { ShiroFilterFactoryBean bean=new ShiroFilterFactoryBean(); bean.setSecurityManager(manager); //配置登入的url和登入成功的url以及驗證失敗的url bean.setLoginUrl("/login"); bean.setSuccessUrl("/home"); bean.setUnauthorizedUrl("/login"); //配置訪問許可權 LinkedHashMap<String, String> filterChainDefinitionMap=new LinkedHashMap<>(); filterChainDefinitionMap.put("/loginUser", "anon"); filterChainDefinitionMap.put("/static/*", "anon"); filterChainDefinitionMap.put("/logout*","anon"); bean.setFilterChainDefinitionMap(filterChainDefinitionMap); return bean; }
比較過來,依然發現,使用INI檔案形式配置攔截器要比程式碼形式更加簡潔.
攔截器的簡單使用
現在我們來拿 /html/login = anon 和 /html/home = authc 以及設定重定向的 authc.loginUrl = /html/login 來簡單說明一下,具體應該如何使用.
我們想讓SpringBoot專案支援Html格式的訪問,那麼我們需要在pom.xml檔案中加入如下的Maven依賴.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
同時,我們要在application.properties檔案中配置如下資訊.設定HTML的存放路徑,
spring.thymeleaf.prefix=classpath:/templates/ spring.mvc.view.suffix=.html
目錄結構如下所示.

然後,我們把ShiroConfiguration配置檔案進行如下的配置.
@Configuration public class ShiroConfiguration { @Bean(name="shiroFilter") public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") DefaultWebSecurityManager manager) { ShiroFilterFactoryBean bean=new ShiroFilterFactoryBean(); bean.setSecurityManager(manager); //配置登入的url和登入成功的url以及驗證失敗的url bean.setLoginUrl("/index"); bean.setSuccessUrl("/home"); bean.setUnauthorizedUrl("/index"); //配置訪問許可權 LinkedHashMap<String, String> filterChainDefinitionMap=new LinkedHashMap<>(); filterChainDefinitionMap.put("/index", "anon"); filterChainDefinitionMap.put("/home", "authc"); filterChainDefinitionMap.put("/**","anon"); bean.setFilterChainDefinitionMap(filterChainDefinitionMap); return bean; } //配置核心安全事務管理器 @Bean(name="securityManager") public DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager manager=new DefaultWebSecurityManager(); return manager; } }
我們在 resources 目錄下建立兩個html頁面,一個login.html,一個home.html,其中程式碼如下所示.
login
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>使用者登入</title> </head> <body> <div style="text-align: center;margin-top: 100px; font-size: 20px;">使用者登入介面</div> </body> </html>
home
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>主頁面</title> </head> <body> <div style="text-align: center;margin-top: 100px; font-size: 20px;">Home介面</div> </body> </html>
然後我們需要編寫兩個介面來訪問login.html和home.html.這裡我建立了一個名為HtmlController的控制器.整體程式碼較為簡單,這裡就直接黏貼出所有程式碼了.如下所示.
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import java.util.Map; @Controller public class HtmlController { @RequestMapping(value = "/index",method = RequestMethod.GET) public String userLoginHtmlAction (){ return "index"; } @RequestMapping(value = "/home",method = RequestMethod.GET) public String userHomeHtmlAction (){ return "home"; } }
然後我們就會猜想有如下情況出現,假設我們可以直接通過瀏覽器訪問 /html/login ,那麼我們會直接訪問到login.html ,但是當我們訪問 /html/home 的時候,由於我們沒有進行使用者登入認證(根本就沒有做登入介面.:grin:),所以我們不可能通過認證,通過登入重指向,瀏覽器仍然會展示login.html 頁面,下面我們就啟動專案來驗證一下.如下所示,攔截成功.

結語(未完待續)
Shiro的攔截器已經配置完成了,下一篇部落格我們將來說一下如何在網頁中使用許可權管理標籤,歡迎繼續關注騷棟.
Demo傳送門
