Shiro安全框架學習
- 一、shiro簡介(簡介內容來自百度百科)
- 二、學習目標
- 三、shiro與spring Security的比較(spring的官網也是用shiro做安全管理的)
- 四、Shiro的整體架構
- 五、Shiro的認證
- 六、Shiro的授權
- 七、Shiro自定義Realm
- 八、自定義Realm
- 九、Shiro的加密
一、shiro簡介(簡介內容來自百度百科)
Apache Shiro是一個強大且易用的Java安全框架,執行身份驗證、授權、密碼學和會話管理,使用Shiro的易于理解的API,您可以快速、輕松地獲得任何應用程式,從最小的移動應用程式到最大的網路和企業應用程式,
三個核心組件:Subject, SecurityManager 和 Realms.
Subject:即“當前操作用戶”,但是,在Shiro中,Subject這一概念并不僅僅指人,也可以是第三方行程、后臺帳戶(Daemon Account)或其他類似事物,它僅僅意味著“當前跟軟體互動的東西”,
Subject代表了當前用戶的安全操作,SecurityManager則管理所有用戶的安全操作,
SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通過SecurityManager來管理內部組件實體,并通過它來提供安全管理的各種服務,
Realm: Realm充當了Shiro與應用安全資料間的“橋梁”或者“連接器”,也就是說,當對用戶執行認證(登錄)和授權(訪問控制)驗證時,Shiro會從應用配置的Realm中查找用戶及其權限資訊,
從這個意義上講,Realm實質上是一個安全相關的DAO:它封裝了資料源的連接細節,并在需要時將相關資料提供給Shiro,當配置Shiro時,你必須至少指定一個Realm,用于認證和(或)授權,配置多個Realm是可以的,但是至少需要一個,
Shiro內置了可以連接大量安全資料源(又名目錄)的Realm,如LDAP、關系資料庫(JDBC)、類似INI的文本配置資源以及屬性檔案等,如果系統默認的Realm不能滿足需求,你還可以插入代表自定義資料源的自己的Realm實作,
二、學習目標
① 認識shiro的整體架構,各組件的概念
② shiro認證,授權的程序
③ shiro自定義的realm、Filter
④ shiro的加密
想更了解“shiro”的小伙伴可以去慕課網搜索“shiro安全框架入門”
鏈接地址:https://www.imooc.com/view/977

三、shiro與spring Security的比較(spring的官網也是用shiro做安全管理的)
1、Shiro比Spring更容易使用,實作和最重要的理解,
2、Spring Security更加知名的唯一原因是因為品牌名稱,
3、“Spring”以簡單而聞名,但諷刺的是很多人發現安裝Spring Security很難
但是Spring Security卻有更好的社區支持,
4、Apache Shiro在Spring Security處理密碼學方面有一個額外的模塊,
5、Spring-security 對spring 結合較好,如果專案用的springmvc ,使用起來很方便,但是如果專案中沒有用到spring,那就不要考慮它了,
6、Shiro 功能強大、且 簡單、靈活,是Apache 下的專案比較可靠,且不跟任何的框架或者容器系結,可以獨立運行,
總結:
Apache shiro: 簡單靈活、可脫離spring、粒度較粗
spring Security: 復雜笨重、不可脫離spring、粒度更細
四、Shiro的整體架構

①上面標記為1的是shiro的主體部分subject,可以理解為當前的操作用戶
② Security Manager為Shiro的核心,shiro是通過security Manager來提供安全服務的,security Manager管理著Session Manager、Cache Manager等其他組件的實體:Authenticator(認證器,管理我們的登錄登出) Authorizer(授權器,負責賦予主體subject有哪些權限) Session Manager(shiro自己實作的一套session管理機制,可以不借助任何web容器的情況下使用session) Session Dao(提供了session的增刪改查操作) cache Manager(快取管理器,用于快取角色資料和權限資料) Pluggable Realms(shiro與資料庫/資料源之間的橋梁,shiro獲取認證資訊、權限資料、角色資料都是通過Realms來獲取)
③ 上圖示記為2的cryptography是用來做加密的,使用它可以非常方便快捷的進行資料加密,
④ 上面箭頭的流程可以這樣理解:主體提交請求到Security Manager,然后由Security Manager呼叫Authenticator去做認證,而Authenticator去獲取認證資料的時候是通過Realms從資料源中來獲取的,然后把從資料源中拿到的認證資訊與主體提交過來的認證資訊做比對,授權器Authorizer也是一樣,
五、Shiro的認證
① 創建Security Manager:Security Manager是用來提供安全服務的,所以在做shiro認證的時候要先創建此物件
② 主體Subject提交請求給Security Manager
③ Security Manager呼叫Authenticator組件做認證
④Authenticator通過Realm來從資料源中獲取認證資料
1、引入依賴
<dependencies>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
</dependencies>
2、測驗用例
package com.shiroDemo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.SimpleAccountRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Before;
import org.junit.Test;
/**
* @program: shiro-demo
* @description: shiro權限測驗類
* @author: Mr.Wang
* @create: 2021-11-05 09:42
**/
public class AuthenticationTest {
//除了SimpleAccountRealm還有JdbcRealm等
SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
//在認證之前先在Realm中添加一個用戶,創建Security Manager的時候要用到Realm
@Before
public void addUser(){
simpleAccountRealm.addAccount("wxc","123456");
}
@Test//Shiro的認證
public void testAutentication(){
//1.構建Security Manager環境(Security Manager是用來提供安全服務的,所以在做shiro認證的時候要先創建此物件,創建Security Manager物件之后要設定Realm)
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(simpleAccountRealm);
//2.獲取向Security Manager提交請求的subject,而主體subject可以通過shiro提供的一個工具類SecurityUtils來獲取
//使用SecurityUtils之前要設定Security Manager環境
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
//3.主體Subject提交請求給Security Manager --> subject.login(token);
//提交請求時需要一個token,所以要先創建token
UsernamePasswordToken token = new UsernamePasswordToken("wxc","123456");
subject.login(token);
//4. shiro提供了一個檢查主體subject是否認證的方法isAuthenticated(),此方法的回傳結果是一個boolean值
System.out.println(subject.isAuthenticated());
//5.注銷
subject.logout();
System.out.println(subject.isAuthenticated());
}
}
執行結果:

六、Shiro的授權
① 創建Security Manager
② 主體subject授權
③ 主體授權是交給Security Manager授權
④ Security Manager呼叫授權器Authorizer授權
⑤ 通過Realm在資料庫或者快取中來獲取授權的資料(角色資料和權限資料)
package com.shiroDemo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.SimpleAccountRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Before;
import org.junit.Test;
/**
* @program: shiro-demo
* @description: shiro權限測驗類
* @author: Mr.Wang
* @create: 2021-11-05 09:42
**/
public class AuthenticationTest {
//除了SimpleAccountRealm還有JdbcRealm等
SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
//在認證之前先在Realm中添加一個用戶,創建Security Manager的時候要用到Realm
@Before
public void addUser(){
//shiro的授權 user,user1都是角色,這里可以自定義多個角色
simpleAccountRealm.addAccount("wxc","123456","admin","user","user1");
}
@Test//Shiro的授權
public void test3(){
//1.構建Security Manager環境(Security Manager是用來提供安全服務的,所以在做shiro認證的時候要先創建此物件,創建Security Manager物件之后要設定Realm)
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(simpleAccountRealm);
//2.獲取向Security Manager提交請求的subject,而主體subject可以通過shiro提供的一個工具類SecurityUtils來獲取
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
//3.主體Subject提交請求給Security Manager --> subject.login(token);
UsernamePasswordToken token = new UsernamePasswordToken("wxc","123456");
subject.login(token);
//4. shiro提供了一個檢查主體subject是否認證的方法isAuthenticated(),此方法的回傳結果是一個boolean值
System.out.println(subject.isAuthenticated());
//校驗角色
subject.checkRoles("user1");
}
}
執行結果:

七、Shiro自定義Realm
**1、**內置Realm,“IniRealm"在專案中新建一個ini檔案,下面的內容的意思是,新建了一個用戶,賬號是xiehuaxin,密碼為123456,此賬號的角色為admin,而admin角色又具有洗掉用戶和更新用戶的權限(多個權限中間用逗號分隔),注意這里的“user:delete”不是一定要這樣寫的,只是一個字串,你也可以寫成"admin=shanchuyonghu”,這要在校驗的時候也用“shanchuyonghu”來匹配就行了,當然這種命名習慣還是不建議的,建議使用“user:delete”這種物件+動作的命名方式,

shiro.ini檔案文字可自定義,路徑也可以放在自己喜歡的路徑下,這里做測驗我放在resources下,
檔案內容:

package com.shiroDemo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Test;
/**
* @program: shiro-demo
* @description: Shiro內置Realm
* @author: Mr.Wang
* @create: 2021-11-05 10:46
**/
public class IniRealmTest {
@Test
public void test(){
//這里設定.ini檔案的路徑
IniRealm iniRealm = new IniRealm("classpath:shiro.ini");
//1.構建Security Manager環境(Security Manager是用來提供安全服務的,所以在做shiro認證的時候要先創建此物件,創建Security Manager物件之后要設定Realm)
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(iniRealm);
//2.獲取向Security Manager提交請求的subject,而主體subject可以通過shiro提供的一個工具類SecurityUtils來獲取 SecurityUtils.setSecurityManager(defaultSecurityManager);//使用SecurityUtils之前要設定Security Manager環境 Subject subject = SecurityUtils.getSubject(); //3.主體Subject提交請求給Security Manager --> subject.login(token); UsernamePasswordToken token = new UsernamePasswordToken("xiehuaxin","123456");//提交請求時需要一個token,所以要先創建token subject.login(token); //4. shiro提供了一個檢查主體subject是否認證的方法isAuthenticated(),此方法的回傳結果是一個boolean值 System.out.println(subject.isAuthenticated());
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
//3.生產token
UsernamePasswordToken token = new UsernamePasswordToken("root","123456");
//4.登錄
subject.login(token);
//判斷是否登錄認證
System.out.println(subject.isAuthenticated());
//5.校驗角色
subject.checkRoles("user");
//6.校驗權限
subject.checkPermission("user:add");
}
}
執行結果:

2、JdbcRealm
1、引入資料庫依賴
<!-- 引入驅動包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>
<!--引入資料源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.4</version>
</dependency>
2、創建資料庫及相關表(Mysql)
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for role_permission
-- ----------------------------
DROP TABLE IF EXISTS `role_permission`;
CREATE TABLE `role_permission` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`role_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`permission` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of role_permission
-- ----------------------------
INSERT INTO `role_permission` VALUES (1, 'admin', 'admin:add');
INSERT INTO `role_permission` VALUES (2, 'admin', 'admin:delete');
INSERT INTO `role_permission` VALUES (3, 'user', 'user:add');
INSERT INTO `role_permission` VALUES (4, 'user', 'user:delete');
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'wxc', '123456');
-- ----------------------------
-- Table structure for user_roles
-- ----------------------------
DROP TABLE IF EXISTS `user_roles`;
CREATE TABLE `user_roles` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`role_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user_roles
-- ----------------------------
INSERT INTO `user_roles` VALUES (1, 'wxc', 'admin');
INSERT INTO `user_roles` VALUES (2, 'wxc', 'user');
SET FOREIGN_KEY_CHECKS = 1;
測驗:
package com.shiroDemo;
import com.alibaba.druid.pool.DruidDataSource;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Test;
/**
* @program: shiro-demo
* @description: JdbcRealm測驗
* @author: Mr.Wang
* @create: 2021-11-05 11:27
**/
public class JdbcRealmTest {
DruidDataSource dataSource = new DruidDataSource();
{//設定資料源
dataSource.setUrl("jdbc:mysql:///test?useSSL=false");
dataSource.setUsername("root");
dataSource.setPassword("root");
}
@Test
public void test(){
//1.創建jdbcReaml物件
JdbcRealm jdbcRealm = new JdbcRealm();
//2.設定資料源
jdbcRealm.setDataSource(dataSource);
//這里需要注意的是,在使用JdbcRealm的時候要設定權限的開關,只有設定為true時才會去查詢權限資料
jdbcRealm.setPermissionsLookupEnabled(true);
//設定認證查詢
String sql = "select password from user where username = ?";
jdbcRealm.setAuthenticationQuery(sql);
//設定角色查詢
String roleSql = "select role_name from user_roles where username = ?";
jdbcRealm.setUserRolesQuery(roleSql);
//設定權限查詢
String perSql = "select permission from role_permission where role_name = ?";
jdbcRealm.setPermissionsQuery(perSql);
//構建Security Manager環境(Security Manager是用來提供安全服務的,所以在做shiro認證的時候要先創建此物件,創建Security Manager物件之后要設定Realm)
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(jdbcRealm);
//獲取向Security Manager提交請求的subject,而主體subject可以通過shiro提供的一個工具類SecurityUtils來獲取
SecurityUtils.setSecurityManager(defaultSecurityManager);//使用SecurityUtils之前要設定Security Manager環境
Subject subject = SecurityUtils.getSubject();
//主體Subject提交請求給Security Manager --> subject.login(token);
UsernamePasswordToken token = new UsernamePasswordToken("wxc","123456");//提交請求時需要一個token,所以要先創建token
subject.login(token);
//shiro提供了一個檢查主體subject是否認證的方法isAuthenticated(),此方法的回傳結果是一個boolean值
System.out.println(subject.isAuthenticated());
subject.checkRoles("admin","user");
}
}
執行結果:

在使用JdbcRealm時,如果沒有設定查詢陳述句,JdbcReal有自己默認的查詢陳述句,
八、自定義Realm
通過查看JdbcRealm或者IniRealm的原始碼可以發現,它們都繼承自AuthorizingRealm,所以要自定義Realm也要使自定義的Realm繼承AuthorizingRealm.
package com.shiroDemo;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @program: shiro-demo
* @description: 自定義Realm
* @author: Mr.Wang
* @create: 2021-11-08 10:25
**/
public class CustomRealm extends AuthorizingRealm {
Map<String,String> userMap = new HashMap<String, String>();
{
userMap.put("wxc","123456");
super.setName("customRealm");//自定義
}
/**
* 用來做授權(就是checkRole,checkPermission時用到的)
* @param principals
* @return
*/
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("自定義授權方法");
//1、現獲取用戶名
String userName = (String)principals.getPrimaryPrincipal();
//2、從資料庫或者快取中獲取角色授權
Set<String> roleSet = getRolesByUserName(userName);
//3、從資料庫或者快取中獲取權限資料
Set<String> perSet = getPermissionsByUserName(userName);
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.setStringPermissions(perSet);
simpleAuthorizationInfo.setRoles(roleSet);
return simpleAuthorizationInfo;
}
/**
* 從資料庫或快取中獲取權限資料(這里模擬資料庫查詢)
* @param userName
* @return
*/
private Set<String> getPermissionsByUserName(String userName) {
Set<String> perSet = new HashSet<String>();
perSet.add("user:add");
perSet.add("user:delete");
return perSet;
}
/**
* 通過用戶名獲取到角色資料(這里為了簡單點就不真的去查詢資料庫了,僅模擬資料庫查詢)
* @param userName
* @return
*/
private Set<String> getRolesByUserName(String userName) {
Set<String> roleSet = new HashSet<String>();
roleSet.add("admin");
roleSet.add("user");
return roleSet;
}
/**
* 用來做認證(就是login時用到的)
* @param token 主體subject傳過來的驗證資訊
* @return
* @throws AuthenticationException
*/
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("自定義認證方法");
//1.先通過主體傳過來的驗證資訊獲取用戶名
String userName = (String)token.getPrincipal();
//2.通過用戶名去資料庫中獲取憑證
String password = getPasswordByUserName(userName);
if(password == null){
return null;
}
//查詢到用戶,則回傳AuthenticationInfo物件
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userName,password,"customRealm");
return simpleAuthenticationInfo;
}
/**
* 通過userName查詢對應用戶密碼(這里直接通過Map獲取)
* @param userName
* @return
*/
private String getPasswordByUserName(String userName) {
return userMap.get(userName);
}
}
測驗自定義Realm
package com.shiroDemo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.junit.Test;
/**
* @program: shiro-demo
* @description: 測驗自定義Realm
* @author: Mr.Wang
* @create: 2021-11-08 10:57
**/
public class CustomRealmTest {
@Test
public void test1(){//自定義Realm測驗
CustomRealm customRealm = new CustomRealm();
//1.構建Security Manager環境(Security Manager是用來提供安全服務的,所以在做shiro認證的時候要先創建此物件,創建Security Manager物件之后要設定Realm)
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(customRealm);
//2.獲取向Security Manager提交請求的subject,而主體subject可以通過shiro提供的一個工具類SecurityUtils來獲取
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
//3.主體Subject提交請求給Security Manager --> subject.login(token);
UsernamePasswordToken token = new UsernamePasswordToken("wxc","123456");
subject.login(token);
//4. shiro提供了一個檢查主體subject是否認證的方法isAuthenticated(),此方法的回傳結果是一個boolean值
System.out.println(subject.isAuthenticated());
subject.checkRoles("admin");
subject.checkPermission("user:delete");
}
}
執行結果:

九、Shiro的加密
1、md5加密
package com.shiroDemo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.junit.Test;
/**
* @program: shiro-demo
* @description: 測驗自定義Realm
* @author: Mr.Wang
* @create: 2021-11-08 10:57
**/
public class CustomRealmTest {
@Test
public void test2(){//shiro加密測驗
CustomRealm customRealm = new CustomRealm();
//1.構建Security Manager環境(Security Manager是用來提供安全服務的,所以在做shiro認證的時候要先創建此物件,創建Security Manager物件之后要設定Realm)
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(customRealm);
//md5加密測驗
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
matcher.setHashAlgorithmName("md5");//設定加密演算法名稱
matcher.setHashIterations(1);//設定加密次數
customRealm.setCredentialsMatcher(matcher);
//2.獲取向Security Manager提交請求的subject,而主體subject可以通過shiro提供的一個工具類SecurityUtils來獲取
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
//3.主體Subject提交請求給Security Manager --> subject.login(token);
UsernamePasswordToken token = new UsernamePasswordToken("wxc","123456");
subject.login(token);
//4. shiro提供了一個檢查主體subject是否認證的方法isAuthenticated(),此方法的回傳結果是一個boolean值
System.out.println(subject.isAuthenticated());
subject.checkRoles("admin");
subject.checkPermission("user:delete");
}
@Test
public void test3(){//因為正常情況,我們設定了加密,資料也是被加密過的,前面自定義的map資料是沒有加密的這路輸入密碼獲取加密后的密碼去替換map的資料
Md5Hash md5Hash = new Md5Hash("123456");
System.out.println(md5Hash.toString());
}
}
因為正常情況,我們設定了加密,資料也是被加密過的,前面自定義的map資料是沒有加密的這里輸入密碼獲取加密后的密碼去替換map的資料


替換后執行測驗代碼:
@Test
public void test2(){//shiro加密測驗
CustomRealm customRealm = new CustomRealm();
//1.構建Security Manager環境(Security Manager是用來提供安全服務的,所以在做shiro認證的時候要先創建此物件,創建Security Manager物件之后要設定Realm)
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(customRealm);
//md5加密測驗
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
matcher.setHashAlgorithmName("md5");//設定加密演算法名稱
matcher.setHashIterations(1);//設定加密次數
customRealm.setCredentialsMatcher(matcher);
//2.獲取向Security Manager提交請求的subject,而主體subject可以通過shiro提供的一個工具類SecurityUtils來獲取
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
//3.主體Subject提交請求給Security Manager --> subject.login(token);
UsernamePasswordToken token = new UsernamePasswordToken("wxc","123456");
subject.login(token);
//4. shiro提供了一個檢查主體subject是否認證的方法isAuthenticated(),此方法的回傳結果是一個boolean值
System.out.println(subject.isAuthenticated());
subject.checkRoles("admin");
subject.checkPermission("user:delete");
}
執行結果:

2、鹽值加密
鹽值加密和md5加密很相似:
先獲取鹽值加密后的密碼,這里"123"表示鹽值是我隨便寫的,在實際專案中可以使用物件的id(userid)來做鹽值進行生成
@Test
public void test3(){
Md5Hash md5Hash = new Md5Hash("123456","123");
System.out.println(md5Hash.toString());
}
執行后復制加密后的密碼替換map集合的密碼:

替換之后,在我們自定義Realm中添加一句代碼:
simpleAuthenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(“123”));
123是鹽值
/**
* 用來做認證(就是login時用到的)
* @param token 主體subject傳過來的驗證資訊
* @return
* @throws AuthenticationException
*/
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("自定義認證方法");
//1.先通過主體傳過來的驗證資訊獲取用戶名
String userName = (String)token.getPrincipal();
//2.通過用戶名去資料庫中獲取憑證
String password = getPasswordByUserName(userName);
if(password == null){
return null;
}
//查詢到用戶,則回傳AuthenticationInfo物件
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userName,password,"customRealm");
simpleAuthenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("123"));
return simpleAuthenticationInfo;
}
執行結果:

shiro的基礎內容大致學習完畢,如想學習更深層的知識點可以看些shiro底層視頻講解!謝謝觀看
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/353275.html
標籤:其他
上一篇:Https安全協議
