Shiro入門學習之自定義Realm實現授權(五)


一、自定義Realm授權

  前提:認證通過,查看Realm接口的繼承關系結構圖如下,要想通過自定義的Realm實現授權,只需繼承AuthorizingRealm並重寫方法即可

 二、實現過程

1、新建module,添加如下pom依賴

<properties>
        <shiro.version>1.4.1</shiro.version>
        <loggingg.version>1.2</loggingg.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>${loggingg.version}</version>
        </dependency>
    </dependencies>

2、新建UserRealm類繼承AuthorizingRealm,重寫方法

public class UserRealm extends AuthorizingRealm {
    private UserService userService = new UserServiceImpl();
    private RoleService roleService = new RoleServiceImpl();
    private PermissionService permissionService = new PermissionServiceImpl();

    /**
     * 做認證
     *
     * @param token
     * @return
     * @throws AuthenticationException
     */
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String username = token.getPrincipal().toString();
        System.out.println("自定義Realm:" + username);
        User user = userService.queryUserByUserName(username);
        if (user != null) {
            List<String> roles = roleService.queryRoleByUserName(username);
            List<String> permissions = permissionService.queryPermissionByUserName(username);
            ActivityUser activityUser = new ActivityUser(user, roles, permissions);
            //參數1:可以傳任意對象|參數2:數據庫中的用戶密碼|參數3:當前類名
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(activityUser, user.getPwd(), this.getName());
            return info;
        } else {
            return null;
        }
    }

    //授權方法
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        System.out.println("doGetAuthorizationInfo被回調了");
        //
        Object primaryPrincipal = principal.getPrimaryPrincipal();
        System.out.println(primaryPrincipal);

        ActivityUser activityUser = (ActivityUser) principal.getPrimaryPrincipal();
        List<String> roles = activityUser.getRoles();
        if (roles != null && roles.size() > 0) {
            info.addRoles(roles);
        }
        List<String> permissins = activityUser.getPermissins();
        if (permissins!=null&&permissins.size()>0)
        {
            info.addStringPermissions(permissins);
        }
        //判斷如果是超級管理員
        //info.addStringPermission("*:*");
        return info;
    }

3、test類測試方法

public class TestAuthorizationRealm
{
    public static void main(String[] args)
    {
        //1.模擬前台傳遞的用戶名和密碼
        String username = "zhangsan";
        String password = "123456";
        //2.創建安全管理器的工廠
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        //3.通過安全管理器工廠獲取安全管理器
        DefaultSecurityManager securityManager = (DefaultSecurityManager)factory.getInstance();
        //4.創建自定義的Realm
        UserRealm userRealm = new UserRealm();
        //5.設置自定義的Realm
        securityManager.setRealm(userRealm);
        //6.將安全管理器綁定到當前運行環境
        SecurityUtils.setSecurityManager(securityManager);
        //7.從當前環境中獲取Subject主體
        Subject subject1 = SecurityUtils.getSubject();
        //8.調用主體的登錄方法
        try
        {
            subject1.login(new UsernamePasswordToken(username,password));
            System.out.println("登錄成功~");

//            Object principal = subject1.getPrincipal();
//            System.out.println(principal);

        } catch (IncorrectCredentialsException e) {
            System.out.println("密碼不正確");
        }catch (UnknownAccountException e) {
            System.out.println("用戶名不存在");
        }

        boolean role1 = subject1.hasRole("role1");
        boolean role2 = subject1.hasRole("role1");
        System.out.println(role1);

        boolean permitted = subject1.isPermitted("user:add");
        System.out.println(permitted);
    }
}

三、分析

1、在進行授權的時候,每進行一次授權都會進行一次回調自定義Realm的doGetAuthorizationInfo方法,驗證如下:

①在授權方法內部打印日志

 

 ②test類做3次授權,查看控制台如下:

2、認證時候進行查庫,查角色、權限,並封裝對象,避免多次調用授權方法導致頻繁查庫導致性能下降

 

 四、總結

1、每次進行授權時,就會調用授權方法(通過打印日志可以驗證)

2、避免在授權回調方法中查庫而導致性能下降

3、授權方法參數可以獲取到認證方法中放入的第一個任意參數(圖中有說明,當然也可以通過subject.getPrincipal()方法獲取該參數),所以我采用封裝的方式,實現多次調用授權方法時也是同一個對象,避免頻繁查庫


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM