Shiro学习记录(详细)
文章目錄
- Shiro學習記錄
- shiro核心組件
- Spring Boot 整合 Shiro
- Shiro 整合 Thymeleaf
Shiro學習記錄
什么是 Shiro
官網:http://shiro.apache.org/
是一款主流的 Java 安全框架,不依賴任何容器,可以運行在 Java SE 和 Java EE 項目中,它的主要作用是對訪問系統的用戶進行身份認證、授權、會話管理、加密等操作。
Shiro 就是用來解決安全管理的系統化框架。
shiro核心組件
用戶、角色、權限(三者關系)
會給角色賦予權限,給用戶賦予角色
1、UsernamePasswordToken,Shiro 用來封裝用戶登錄信息,使用用戶的登錄信息來創建令牌 Token。
2、SecurityManager,Shiro 的核心部分,負責安全認證和授權。
3、Suject,Shiro 的一個抽象概念,包含了用戶信息。
4、Realm,開發者自定義的模塊,根據項目的需求,驗證和授權的邏輯全部寫在 Realm 中。
5、AuthenticationInfo,用戶的角色信息集合,認證時使用。
6、AuthorzationInfo,角色的權限信息集合,授權時使用。
7、DefaultWebSecurityManager,安全管理器,開發者自定義的 Realm 需要注入到 DefaultWebSecurityManager 進行管理才能生效。
8、ShiroFilterFactoryBean,過濾器工廠,Shiro 的基本運行機制是開發者定制規則,Shiro 去執行,具體的執行操作就是由 ShiroFilterFactoryBean 創建的一個個 Filter 對象來完成。
Shiro 的運行機制如下圖所示:
Spring Boot 整合 Shiro
1、創建 Spring Boot 應用,集成 Shiro 及相關組件,pom.xml:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId> </dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId> </dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.3.1.tmp</version> </dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.3.1.tmp</version> </dependency><dependency><groupId>com.github.theborakompanioni</groupId><artifactId>thymeleaf-extras-shiro</artifactId><version>2.0.0</version> </dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.5.3</version> </dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional> </dependency> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions> </dependency>Account.java
package com.monkey.springbootshrio.entity;import lombok.Data;@Data public class Account {private Integer id;private String username;private String password;private String perms;private String role; }數據庫表:
2、自定義 Shiro 過濾器
package com.monkey.springbootshrio.realm;import com.monkey.springbootshrio.entity.Account; import com.monkey.springbootshrio.service.AccountService; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired;import java.util.HashSet; import java.util.Set;public class AccountRealm extends AuthorizingRealm{@Autowiredprivate AccountService accountService;/*** 授權(登陸之后)* @param principalCollection* @return*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {//獲取當前登錄的用戶信息Subject subject = SecurityUtils.getSubject();Account account = (Account)subject.getPrincipal();//設置角色Set<String> roles = new HashSet<>();roles.add(account.getRole());SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);//設置權限info.addStringPermission(account.getPerms());return info;}/*** 認證(登錄)* @param authenticationToken* @return* @throws AuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;//客戶端傳過來的用戶名和密碼Account account = accountService.findByUsername(token.getUsername());//從數據庫中取出用戶名進行驗證if(account != null){return new SimpleAuthenticationInfo(account,account.getPassword(),getName());//驗證密碼 如果驗證不通過則拋出異常}return null;//拋出用戶不存在} }3、配置類
package com.monkey.springbootshrio.config;import at.pollux.thymeleaf.shiro.dialect.ShiroDialect; import com.monkey.springbootshrio.realm.AccountRealm; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;import java.util.Hashtable; import java.util.Map;@Configuration public class ShiroConfig {@Beanpublic ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();factoryBean.setSecurityManager(defaultWebSecurityManager);//認證和授權(權限設置)Map<String,String> map = new Hashtable<>();map.put("/main","authc");map.put("/manage","perms[manage]");map.put("/administrator","roles[administrator]");factoryBean.setFilterChainDefinitionMap(map);//設置登錄頁面factoryBean.setLoginUrl("/login");//設置未授權頁面factoryBean.setUnauthorizedUrl("/unauth");return factoryBean;}@Beanpublic DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("accountRealm") AccountRealm accountRealm){DefaultWebSecurityManager manager = new DefaultWebSecurityManager();manager.setRealm(accountRealm);return manager;}@Beanpublic AccountRealm accountRealm(){return new AccountRealm();}}編寫認證和授權規則:
認證過濾器
anon:無需認證。
authc:必須認證。
authcBasic:需要通過 HTTPBasic 認證。
user:不一定通過認證,只要曾經被 Shiro 記錄即可,比如:記住我。
授權過濾器
perms:必須擁有某個權限才能訪問。
role:必須擁有某個角色才能訪問。
port:請求的端口必須是指定值才可以。
rest:請求必須基于 RESTful,POST、PUT、GET、DELETE。
ssl:必須是安全的 URL 請求,協議 HTTPS。
例子:
創建 3 個頁面,main.html、manage.html、administrator.html
訪問權限如下:
1、必須登錄才能訪問 main.html
2、當前用戶必須擁有 manage 授權才能訪問 manage.html
3、當前用戶必須擁有 administrator 角色才能訪問 administrator.html
Shiro 整合 Thymeleaf
1、pom.xml 引入依賴(所有依賴見上pom文件dependency代碼)
2、配置類添加 ShiroDialect
@Bean public ShiroDialect shiroDialect(){return new ShiroDialect(); }AccountController.java
package com.monkey.springbootshrio.controller;import com.monkey.springbootshrio.entity.Account; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*;@Controller public class AccountController {@GetMapping("/{url}")public String redirect(@PathVariable("url") String url){return url;}@PostMapping("/login")public String login(String username, String password, Model model){Subject subject = SecurityUtils.getSubject();UsernamePasswordToken token = new UsernamePasswordToken(username,password);try{subject.login(token);//進入到realm里面認證方法Account account = (Account)subject.getPrincipal();subject.getSession().setAttribute("account",account);return "index";}catch (UnknownAccountException e){e.printStackTrace();model.addAttribute("msg","用戶名錯誤!");return "login";}catch (IncorrectCredentialsException e){e.printStackTrace();model.addAttribute("msg","密碼錯誤!");return "login";}}@GetMapping("/unauth")@ResponseBody //直接返回內容,不映射到頁面public String unauth(){return "未授權,無法訪問!";}@GetMapping("/logout")public String logout(){Subject subject = SecurityUtils.getSubject();subject.logout();return "login";}}login.html
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head><meta charset="UTF-8"><title>login</title><link rel="shortcut icon" href="#" /> </head> <body><form action="/login" method="post"><span th:text="${msg}" style="color: red;"></span><br />用戶名:<input type="text" name="username" placeholder="input your name" /><br />密碼:<input type="password" name="password" placeholder="input your password" /><br /><input type="submit" value="提交" /></form> </body> </html>index.html
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro"> <head><meta charset="UTF-8"><title>index</title><link rel="shortcut icon" href="#" /> </head> <body><h1>index</h1><div th:if="${session.account != null}"><span th:text="${session.account.username}+'歡迎回來!'"></span><span><a href="logout">退出</a></span></div><a href="/main">main</a> <br/><div shiro:hasPermission="manage"><a href="/manage">manage</a> <br/></div><div shiro:hasRole="administrator"><a href="/administrator">administrator</a> <br/></div></body> </html>運行截圖(例:ls)
完整源碼獲取github:
https://github.com/monkeyhlj/spring-study
總結
以上是生活随笔為你收集整理的Shiro学习记录(详细)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mybatis-plus学习记录(详细)
- 下一篇: 动态规划(Dynamic Program