Shiro入門10:自定義Realm進行授權

需求:

    |---前一個的程序通過shiro-permission.ini作爲數據源對權限信息進行靜態配置,實際開發中從數據庫中獲取權限數據
        就需要自定義realm,由Realm從數據庫查詢權限數據。
    |---Realm根據用戶身份查詢權限數據,將權限數據返回給Authorizer(授權器)
    |
    |---自定義Realm【實現AuthorizingRealm】
        |---在原來自定義的Realm中修改doGetAuthorizationInfo




配置shiro-realm.ini文件【跟上面一樣,配置realm到securityManager中】

Edit
[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測試:

     |---需要注意的是:下面方法中部分代碼代替了數據庫的查詢過程
     |---重寫實現方法:doGetAuthorizationInfo(PrincipalCollection principals)

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授權功能

     |---主要是要注意好是否已經在上面的配置文件中綁定了測試的Realm

Edit

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
}




授權的流程的總結:


  1. subject進行授權,調用方法:isPermitted("permission串");或isAllPermitted();【查看permission串在不在權限範圍內】
  2. 由SecurityManager執行授權,最終通過ModularRealmAuthorizer執行授權
  3. ModularRealmAuthorizer執行Realm【上面自定義的CustomRealm】從數據庫查詢權限數據
  4. 【調用Realm的:doGetAuthorizationInfo(PrincipalCollection principals) 】
  5. Realm從數據庫查詢權限數據,返回ModularRealmAuthorizer【這個詞和認證的方法容易混淆,記得注意區分
  6.  ModularRealmAuthorizer進行權限數據的匹配:調用PermissionResolver進行權限比對。
  7. 如果比對後:isPermitted(中的"permission串"),在Realm查詢到的權限數據中,說明授權通過【用戶訪問的Permission串具有權限;否則,沒有權限,拋出異常】

此文老貓原創,轉載請加本文連接:http://blog.csdn.net/nthack5730/article/details/51019516

更多有關老貓的文章:http://blog.csdn.net/nthack5730




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章