需求:
配置shiro-realm.ini文件【跟上面一樣,配置realm到securityManager中】
[main]
#自定義realm
customRealm = cn.marer.shiro.realm.CustomRealm
#將realm設置到securityManager,相當於Spring中的注入
securityManager.realms = $customRealm
此文老貓原創,轉載請加本文連接:http://blog.csdn.net/nthack5730/article/details/51019516
更多有關老貓的文章:http://blog.csdn.net/nthack5730
自定義Realm測試:
import java.util.ArrayList;
import java.util.List;
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;
/**
* 自定義Realm
* @author CatScan
*
*/
public class CustomRealm extends AuthorizingRealm{
final String realmName="customRealm";
//設置realmName
@Override
public void setName(String name) {
super.setName(realmName);
}
//用於認證
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
// 第一步從token中取出用戶發送過來的身份信息
String userCode = (String) token.getPrincipal();
//第二步根據用戶輸入的帳號從數據庫查詢
//...
String pwd = "11111";
//如果查詢不到返回null
//如果查詢到,返回認證信息:AuthenticationInfo
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userCode, pwd, this.getName());
return simpleAuthenticationInfo;
}
//用於授權
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//從principals獲取主身份信息
//將getPrimaryPrincipal()返回的值強制轉換爲真實身份信息【在上邊的doGetAuthenticationInfo()認證通過填充到SimpleAuthenticationInfo中的身份信息】
String userCode = (String) principals.getPrimaryPrincipal();
//根據身份信息獲取權限信息
//先鏈接數據庫。。。
//模擬從數據庫獲取數據
List<String> permissions = new ArrayList<String>();
permissions.add("user:create");//用戶的創建權限
permissions.add("user:update");//用戶的修改
permissions.add("item:add");//商品的添加權限
//....等等權限
//查到權限數據,返回
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//將List裏面的權限填充進去
simpleAuthorizationInfo.addStringPermissions(permissions);
return simpleAuthorizationInfo;
}
}
此文老貓原創,轉載請加本文連接:http://blog.csdn.net/nthack5730/article/details/51019516
更多有關老貓的文章:http://blog.csdn.net/nthack5730
測試類:測試自定義Realm授權功能
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Test;
public class AuthorizationTest {
//===========================================
// 自定義Realm進行授權測試:角色授權、資源授權
//===========================================
@Test
public void testAuthorizationCustomRealm(){
//創建一個SecurityManager工廠
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");
//創建SecurityManager
SecurityManager sm = factory.getInstance();
//將SecurityManager設置到系統運行環境,和Spring整合後將SecurityManager配置到Spring容器中,一般單例管理
SecurityUtils.setSecurityManager(sm);
//創建Subject
Subject subject = SecurityUtils.getSubject();
//創建token令牌
UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "11111");
//執行認證
try {
subject.login(token);
} catch (AuthenticationException e) {
// TODO 自動生成的 catch 塊
e.printStackTrace();
}
System.out.println("認證狀態:" + subject.isAuthenticated());
//認證通過後執行授權
//===========================================
// 基於角色授權
//===========================================
//hasRole方法傳入的是角色標識
// boolean isHasRole = subject.hasRole("role1");
// System.out.println("正確角色,角色有權限--->" + isHasRole);
// //傳入錯誤的角色
// boolean isHasRole2 = subject.hasRole("role12");
// System.out.println("錯誤角色,角色有權限--->" + isHasRole2);
// //判斷多個角色
// boolean hasAllRoles = subject.hasAllRoles(Arrays.asList("role1","role2"));
// System.out.println("多個角色判斷--->" + hasAllRoles);
//使用check方法進行授權,如果不通過,會拋出異常
// try {
// subject.checkRole("role12");
// } catch (AuthorizationException e) {
// // TODO 自動生成的 catch 塊
// e.printStackTrace();
// }
//===========================================
// 基於資源授權
//===========================================
//調用isPermitted(),就會調用CustomRealm從數據庫查數據權限數據
//isPermitted()傳入權限標識符,判斷user:create:1是否在CustomRealm查詢到權限數據之內
boolean isPermited = subject.isPermitted("user:create:1");
System.out.println("資源有權限,單個權限判斷--->" + isPermited);
//傳入的是資源標識符,多個權限判斷
boolean isPermitedAll = subject.isPermittedAll("user:create","user:update","user:delete");
System.out.println("資源有權限,多個權限判斷--->" + isPermitedAll);
//資源權限也支持check,如果不通過,也會拋異常
try {
subject.checkPermission("item:add");
} catch (AuthorizationException e) {
// TODO 自動生成的 catch 塊
e.printStackTrace();
System.out.println(e.toString());
}
subject.getPrincipal();
}//method
}
授權的流程的總結:
- subject進行授權,調用方法:isPermitted("permission串");或isAllPermitted();【查看permission串在不在權限範圍內】
- 由SecurityManager執行授權,最終通過ModularRealmAuthorizer執行授權
- ModularRealmAuthorizer執行Realm【上面自定義的CustomRealm】從數據庫查詢權限數據
- 【調用Realm的:doGetAuthorizationInfo(PrincipalCollection principals) 】
- Realm從數據庫查詢權限數據,返回ModularRealmAuthorizer【這個詞和認證的方法容易混淆,記得注意區分】
- ModularRealmAuthorizer進行權限數據的匹配:調用PermissionResolver進行權限比對。
- 如果比對後:isPermitted(中的"permission串"),在Realm查詢到的權限數據中,說明授權通過【用戶訪問的Permission串具有權限;否則,沒有權限,拋出異常】
此文老貓原創,轉載請加本文連接:http://blog.csdn.net/nthack5730/article/details/51019516
更多有關老貓的文章:http://blog.csdn.net/nthack5730