shiro認證管理
阿新 • 來源:網路 • 發佈:2021-02-14
1、認證
身份認證就是判斷一個使用者是否為合法使用者的處理過程。通過核對使用者輸入的使用者名稱和口令,判斷身份是否正確。
2、shiro中認證關鍵物件
subject:主體
訪問系統的使用者,主體可以是使用者、程式等,進行認證都稱為主體。
Principal:身份資訊
例如:是主體(subject)進行身份認證的標識,標識必須具有唯一性。一個主體可以有多個身份,例如可以用手機號、賬號、郵箱進行賬號密碼登陸。
Credential:憑證資訊
口令,只有主體自己知道的安全資訊,例如,密碼,證書等。
3、認證流程
登陸使用者,攜帶身份和口令(憑證),將兩種資訊打包成一個令牌,shirofilter進行攔截,將令牌拿到安全管理器中,呼叫認證器,認證器呼叫reaml獲取資料庫中資料,如果身份資訊與口令與原始資料中的存留資訊一致,就屬於認證成功,放行進入系統,否則失敗。

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("密碼錯誤!!!");
}
}
}
