shiro認證管理
阿新 • • 發佈:2021-02-14
1、認證
身份認證就是判斷一個使用者是否為合法使用者的處理過程。通過核對使用者輸入的使用者名稱和口令,判斷身份是否正確。
2、shiro中認證關鍵物件
subject:主體
訪問系統的使用者,主體可以是使用者、程式等,進行認證都稱為主體。
Principal:身份資訊
例如:是主體(subject)進行身份認證的標識,標識必須具有唯一性。一個主體可以有多個身份,例如可以用手機號、賬號、郵箱進行賬號密碼登陸。
Credential:憑證資訊
口令,只有主體自己知道的安全資訊,例如,密碼,證書等。
3、認證流程
登陸使用者,攜帶身份和口令(憑證),將兩種資訊
4、認證開發
4.1 引入依賴
<!--編碼處理 --> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> </properties> <!--JDk版本的引入 --> <profiles> <profile> <id>development</id> <activation> <jdk>1.8</jdk> <activeByDefault>true</activeByDefault> </activation> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion> </properties> </profile> </profiles> <!--shiro包引入 --> <dependencies> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.5.3</version> </dependency> </dependencies>
4.2 shiro.ini配置檔案
在resource目錄下,該配置存放的本次認證的賬號和密碼。
[users]
zhangsan=123
lisi=456
wangwu=789
4.3 認證程式碼
package com.demo; 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.mgt.DefaultSecurityManager; import org.apache.shiro.realm.text.IniRealm; import org.apache.shiro.subject.Subject; public class ShiroDemo { public static void main(String[] args) { //建立安全管理器 DefaultSecurityManager defaultSecurityManager=new DefaultSecurityManager(); //建立realm 讀取配置檔案中的使用者名稱 密碼 defaultSecurityManager.setRealm(new IniRealm("classpath:shiro.ini")); //使用工具,將安裝工具類中設定預設安全管理器 SecurityUtils.setSecurityManager(defaultSecurityManager); //實用工具類獲取登入主體 Subject subject = SecurityUtils.getSubject(); //建立令牌 使用者名稱+密碼 UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123"); try { System.out.println("認證狀態:"+subject.isAuthenticated()); subject.login(token);//使用者登入 這裡加入了使用者登陸資訊 System.out.println("認證狀態:"+subject.isAuthenticated()); //驗證登陸資訊 System.out.println("登入成功!!"); } catch (UnknownAccountException e) { e.printStackTrace(); System.out.println("使用者名稱錯誤!!"); }catch (IncorrectCredentialsException e){ e.printStackTrace(); System.out.println("密碼錯誤!!!"); } } }
其他認證異常
DisabledAccountException(賬號被禁用)
LockedAccountException(賬號被鎖定)
ExcessiveAttemptsException(登入失敗次數過多)
ExpiredCredentialsException(憑證過期)
5、加鹽認證
md5工具,加入不同字串數字後密碼的強度
package com.demo.md5;
import org.apache.shiro.crypto.hash.Md5Hash;
/**
* 三種組合的md5加密
* @author Administrator
*
*/
public class ShiroMD5 {
public static void main(String[] args) {
Md5Hash md5Hash=new Md5Hash("123"); //這個容易被反編譯 安全性不高
System.out.println(md5Hash.toHex());
//md5+salt md5加密+自定義字串
Md5Hash md5Hash2=new Md5Hash("123","x0*&p");
System.out.println(md5Hash2.toHex());
//md5+salt+hash雜湊
Md5Hash md5Hash3=new Md5Hash("123","x0*&p",1024);
System.out.println(md5Hash3.toHex());
}
}
效果:
202cb962ac59075b964b07152d234b70
0ea1434575ac41da89b2335d8dde11e1
efe2cdcad63be25838e3847becd43df4
自定義CustomerRealm類中,需要繼承AuthorizingRealm類,進行登陸賬號、密碼、鹽salt的定義,當然真實情況,賬號密碼應該從資料庫中獲取。salt應該作為隨機字串變數存在。
package com.demo.md5;
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.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
/**
* 自定義md5+salt realm
*/
public class CustomerRealm extends AuthorizingRealm {
//授權方法
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
return null;
}
//認證方法
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//獲取身份資訊
String principal = (String) token.getPrincipal();
//這裡的zhangsan就是資料查出來的,模擬 這裡的賬號、密碼按道理是在資料庫的變數
if("zhangsan".equals(principal)){
String password = "efe2cdcad63be25838e3847becd43df4";
String salt = "x0*&p"; //自定義加鹽
//資料庫的使用者名稱
//資料庫md5+salt之後的密碼
//註冊時的隨機鹽
//realm的名字
return new SimpleAuthenticationInfo(principal,password,
ByteSource.Util.bytes(salt),this.getName());
}
return null;
}
}
測試類
package com.demo.md5;
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.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
public class TestAuthenticatorCusttomerRealm {
public static void main(String[] args) {
//建立securityManager
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
//IniRealm realm = new IniRealm("classpath:shiro.ini");
//設定為自定義realm獲取認證資料
CustomerRealm customerRealm = new CustomerRealm();
//設定md5加密
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName("MD5"); //新增加密字串
credentialsMatcher.setHashIterations(1024);//設定雜湊次數 打亂順序
customerRealm.setCredentialsMatcher(credentialsMatcher); //在customerRealm設定加密後的密碼驗證器//設定自定義realm
defaultSecurityManager.setRealm(customerRealm); //將自定義的realm設定到安全管理中
//將安裝工具類中設定預設安全管理器
SecurityUtils.setSecurityManager(defaultSecurityManager); //將安全管理設定到安全工具中
//獲取主體物件
Subject subject = SecurityUtils.getSubject();
//建立token令牌
UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123");
try {
//subject物件 中方法 +加鹽 +驗證+許可權操作
subject.login(token);//使用者登入,shiro會自動將token中的password在自定義realm中加上鹽去處理
System.out.println("登入成功~~");
} catch (UnknownAccountException e) {
e.printStackTrace();
System.out.println("使用者名稱錯誤!!");
}catch (IncorrectCredentialsException e){
e.printStackTrace();
System.out.println("密碼錯誤!!!");
}
}
}
6、授權認證
CustomerRealm類中新增可放通的角色role,新增可訪問資源"user:*:01"。
package com.demo.grant;
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.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
//授權領域
public class CustomerRealm extends AuthorizingRealm {
//授權方法
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//獲取主要身份
String primaryPrincipal = (String) principals.getPrimaryPrincipal();
System.out.println("primaryPrincipal = " + primaryPrincipal);
//根據身份資訊 使用者名稱 獲取當前使用者的角色資訊,以及許可權資訊 xiaochen admin user
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//將模擬資料庫中查詢角色資訊賦值給許可權物件
simpleAuthorizationInfo.addRole("admin");
simpleAuthorizationInfo.addRole("user");
//將資料庫中查詢許可權資訊賦值給許可權物件
//對使用者下01例項具有所有許可權 這是資源路徑例項
simpleAuthorizationInfo.addStringPermission("user:*:01");
//對product下一切資源例項具有建立許可權,*可以省略
simpleAuthorizationInfo.addStringPermission("product:create");
return simpleAuthorizationInfo;
}
//認證方法
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String principal = (String) token.getPrincipal();
if("zhangsan".equals(principal)){
//模擬資料庫中已經md5加鹽處理過的密碼
String password = "efe2cdcad63be25838e3847becd43df4";
String salt = "x0*&p"; //需要這個解開密碼
return new SimpleAuthenticationInfo(principal,password,
ByteSource.Util.bytes(salt),this.getName());
}
return null;
}
}
測試類
package com.demo.md5;
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.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
public class TestAuthenticatorCusttomerRealm {
public static void main(String[] args) {
//建立securityManager
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
//IniRealm realm = new IniRealm("classpath:shiro.ini");
//設定為自定義realm獲取認證資料
CustomerRealm customerRealm = new CustomerRealm();
//設定md5加密
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName("MD5"); //新增加密字串
credentialsMatcher.setHashIterations(1024);//設定雜湊次數 打亂順序
customerRealm.setCredentialsMatcher(credentialsMatcher); //MD5加密器//設定自定義realm
defaultSecurityManager.setRealm(customerRealm); //將自定義的realm設定到安全管理中
//將安裝工具類中設定預設安全管理器
SecurityUtils.setSecurityManager(defaultSecurityManager); //將安全管理設定到安全工具中
//獲取主體物件
Subject subject = SecurityUtils.getSubject();
//建立token令牌
UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123");
try {
//subject物件 中方法 +加鹽 +驗證+許可權操作 主體物件呼叫login方法
subject.login(token);//使用者登入,shiro會自動將token中的password在自定義realm中加上鹽去處理
System.out.println("登入成功~~");
} catch (UnknownAccountException e) {
e.printStackTrace();
System.out.println("使用者名稱錯誤!!");
}catch (IncorrectCredentialsException e){
e.printStackTrace();
System.out.println("密碼錯誤!!!");
}
}
}