SpringBoot淺析安全管理之Shiro框架
Shiro 簡介
Apache Shiro 是一個開源的輕量級的 Java 安全框架,它提供身份驗證、授權、密碼管理以及會話管理等功能。相對於 Spring Security ,Shiro 框架更加直觀、易用,同時也能提供健壯的安全性。
在傳統的 SSM 框架中,手動整合 Shiro 的配置步驟還是比較多的,針對 Spring Boot ,Shiro 官方提供瞭 shiro-spring-boot-web-starter 用來簡化 Shiro 在 Spring Boot 中的配置。
整合 Shiro
1. 創建項目
首先創建一個普通的 Spring Boot Web 項目,添加 Shiro 依賴以及頁面模板依賴
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-web-starter</artifactId> <version>1.4.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>com.github.theborakompanioni</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> <version>2.0.0</version> </dependency>
這裡不需要添加 spring-boot-starter-web 依賴,shiro-spring-boot-web-starter 中已經依賴瞭 spring-boot-starter-web 。同時,此處使用 Thymeleaf 模板,為瞭在 Thymeleaf 使用 shiro 標簽,加入瞭 thymeleaf-extras-shiro 依賴。
2. Shiro基本配置
在 application.properties 中配置 Shiro 的基本信息
# 開啟 Shiro 配置,默認為 true
shiro.enabled=true
# 開啟 Shiro Web 配置,默認為 true
shiro.web.enabled=true
# 配置登錄地址,默認為 /login.jsp
shiro.loginUrl=/login
# 配置登錄成功的地址,默認為 /
shiro.successUrl=/index
# 未獲授權默認跳轉地址
shiro.unauthorizedUrl=/unauthorized
# 是否允許通過 URL 參數實現會話跟蹤,如果網站支持 Cookie,可以關閉此選項,默認為 true
shiro.sessionManager.sessionIdUrlRewritingEnabled=true
# 是否允許通過 Cookie 實現會話跟蹤,默認為 true
shiro.sessionManager.sessionIdCookieEnabled=true
然後在 Java 代碼中配置 Shiro ,提供兩個最基本的 Bean 即可
@Configuration public class ShiroConfig { @Bean public Realm realm() { TextConfigurationRealm realm = new TextConfigurationRealm(); realm.setUserDefinitions("sang=123,user\n admin=123,admin"); realm.setRoleDefinitions("admin=read,write\n user=read"); return realm; } @Bean public ShiroFilterChainDefinition shiroFilterChainDefinition() { DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition(); chainDefinition.addPathDefinition("/login", "anon"); chainDefinition.addPathDefinition("/doLogin", "anon"); chainDefinition.addPathDefinition("/logout", "logout"); chainDefinition.addPathDefinition("/**", "authc"); return chainDefinition; } @Bean public ShiroDialect shiroDialect() { return new ShiroDialect(); } }
代碼解釋:
- 這裡提供兩個關鍵的 Bean ,一個是 Realm,另一個是 ShiroFilterChainDefinition 。至於 ShiroDialect 則是為瞭支持在 Thymeleaf 中使用 Shiro 標簽,如果不在 Thymeleaf 中使用 Shiro 標簽,那麼可以不提供 ShiroDialect
- Realm 可以是自定義的 Realm,也可以是 Shiro 提供的 Realm,簡單起見,此處沒有配置數據庫連接,直接配置瞭兩個用戶:sang/123 和 admin/123 ,分別對應角色 user 和 admin。
- ShiroFilterChainDefinition Bean 中配置瞭基本的過濾規則 ,“/login” 和 “/doLogin”,可以匿名訪問,“/logout”是一個註銷登錄請求,其餘請求則都需要認證後才能訪問
然後配置登錄接口以及頁面訪問接口
@Controller public class UserController { @PostMapping("/doLogin") public String doLogin(String username, String password, Model model) { UsernamePasswordToken token = new UsernamePasswordToken(username, password); Subject subject = SecurityUtils.getSubject(); try { subject.login(token); } catch (AuthenticationException e) { model.addAttribute("error", "用戶名或密碼輸入錯誤!"); return "login"; } return "redirect:/index"; } @RequiresRoles("admin") @GetMapping("/admin") public String admin() { return "admin"; } @RequiresRoles(value = {"admin", "user"}, logical = Logical.OR) @GetMapping("/user") public String user() { return "user"; } }
代碼解釋:
- 在 doLogin 方法中,首先構建一個 UsernamePasswordToken 實例,然後獲取一個 Subject 對象並調用該對象中的 login 方法執行登錄操作,在登錄操作執行過程中,當有異常拋出時,說明登錄失敗,攜帶錯誤信息返回登錄視圖;當登錄成功時,則重定向到“/index”
- 接下來暴露兩個接口“/admin”和“/user”,對於“/admin”接口,需要具有 admin 角色才可以訪問;對於“/user”接口,具備 admin 角色 和 user角色其中任意一個即可訪問
對於其他不需要角色就能訪問的接口,直接在 WebMvc 中配置即可
@Configuration public class WebMvcConfig implements WebMvcConfigurer{ @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/login").setViewName("login"); registry.addViewController("/index").setViewName("index"); registry.addViewController("/unauthorized").setViewName("unauthorized"); } }
接下來創建全局異常處理器進行全局異常處理,此處主要是處理授權異常
@ControllerAdvice public class ExceptionController { @ExceptionHandler(AuthorizationException.class) public ModelAndView error(AuthorizationException e) { ModelAndView mv = new ModelAndView("unauthorized"); mv.addObject("error", e.getMessage()); return mv; } }
當用戶訪問未授權的資源時,跳轉到 unauthorized 視圖中,並攜帶出錯誤信息。
配置完成後,最後在 resources/templates 目錄下創建 5 個 HTML 頁面進行測試。
(1)index.html
<!DOCTYPE html> <html lang="en" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h3>Hello, <shiro:principal/></h3> <h3><a href="/logout" rel="external nofollow" >註銷登錄</a></h3> <h3><a shiro:hasRole="admin" href="/admin" rel="external nofollow" >管理員頁面</a></h3> <h3><a shiro:hasAnyRoles="admin,user" href="/user" rel="external nofollow" >普通用戶頁面</a></h3> </body> </html>
(2)login.html
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div> <form action="/doLogin" method="post"> <input type="text" name="username"><br> <input type="password" name="password"><br> <div th:text="${error}"></div> <input type="submit" value="登錄"> </form> </div> </body> </html>
(3)user.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>普通用戶頁面</h1> </body> </html>
(4)admin.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>管理員頁面</h1> </body> </html>
(5)unauthorized.html
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div> <h3>未獲授權,非法訪問</h3> <h3 th:text="${error}"></h3> </div> </body> </html>
3. 測試
啟動項目,訪問登錄頁面,使用 sang/123 登錄
註意:由於 sang 用戶不具備 admin 角色,因此登錄成功後的頁面沒有前往管理員頁面的超鏈接。
然後使用 admin/123 登錄。
如果用戶使用 sang 登錄,然後去訪問:http://localhost:8080/admin,會跳轉到未授權頁面
以上通過一個簡單的案例展示瞭如何在 Spring Boot 中整合 Shiro 以及如何在 Thymeleaf 中使用 Shiro 標簽,一旦整合成功,接下來 Shiro 的用法就和原來的一模一樣。此處主要將 Spring Boot 整合 Shiro,對於 Shiro 的其它用法,可以參考 Shiro 官方文檔。
到此這篇關於SpringBoot淺析安全管理之Shiro框架的文章就介紹到這瞭,更多相關SpringBoot Shiro框架內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- 詳解Java springboot 整合Shiro框架
- 解決springboot+shiro+thymeleaf頁面級元素的權限控制問題
- SpringBoot整合Shiro實現權限控制的代碼實現
- springboot整合Shiro的步驟
- Java shiro安全框架使用介紹