Fork me on GitHub

Apache-Shiro自定义Realm实战

自定义Realm简介 

  一般情况现自定义Realm是继承AuthorizingRealm。

  Realm的继承关系:AuthorizingRealm->AuthenticatingRealm->CachingRealm->Realm。

步骤

  1. 创建一个类 ,继承AuthorizingRealm。
  2. 重写授权方法 doGetAuthorizationInfo。
  3. 重写认证方法 doGetAuthenticationInfo。

重写方法介绍

  1. 当用户登陆的时候会调用 doGetAuthenticationInfo。
  2. 进行权限校验的时候会调用: doGetAuthorizationInfo。

实体对象介绍 

  1. UsernamePasswordToken:对应就是 shiro的token中有Principal和Credential,继承关系UsernamePasswordToken-》HostAuthenticationToken-》AuthenticationToken
  2. SimpleAuthorizationInfo:代表用户角色权限信息
  3. SimpleAuthenticationInfo:代表该用户的认证信息

代码实战

自定义CustomRealm

/**
 * @ClassName: CustomRealm
 * 自定义Realm
 * @Description:
 * @Author: Coding_wxb
 * @Date 2019.08.02 2:24
 */
public class CustomRealm extends AuthorizingRealm {
    /**
     *模拟用户
     **/
    private final Map<String,String> userInfoMap = new HashMap<>();
    {
        userInfoMap.put("woxbwo","123");
        userInfoMap.put("zbbiex","456");
    }
    /**
     *模拟role -> permission
     **/
    private final Map<String, Set<String>> permissionMap = new HashMap<>();
    {
        Set<String> set1 = new HashSet<>();
        Set<String> set2 = new HashSet<>();
        set1.add("video:find");
        set1.add("video:buy");
        set2.add("video:add");
        set2.add("video:delete");
        permissionMap.put("woxbwo",set1);
        permissionMap.put("zbbiex",set2);

    }
    /**
     *模拟user -> role
     **/
    private final Map<String,Set<String>> roleMap = new HashMap<>();{
        Set<String> set1 = new HashSet<>();
        Set<String> set2 = new HashSet<>();
        set1.add("role1");
        set1.add("role2");
        set2.add("root");
        roleMap.put("woxbwo",set1);
        roleMap.put("zbbiex",set2);

    }
    /**
     *@description:
     * 该方法会在权限校验是调用
     *@params:  [principals]
     *@return:  org.apache.shiro.authz.AuthorizationInfo
     **/
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("权限 doGetAuthorizationInfo");
        String name = (String)principals.getPrimaryPrincipal();
        Set<String> permissions = getPermissionsByNameFromDB(name);
        Set<String> roles = getRolesByNameFromDB(name);
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.setRoles(roles);
        simpleAuthorizationInfo.setStringPermissions(permissions);
        return simpleAuthorizationInfo;
    }
    /**
     *@description:
     * 该方法会在用户身份认证时调用
     *@params:  [token]
     *@return:  org.apache.shiro.authc.AuthenticationInfo
     **/
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("认证 doGetAuthenticationInfo");
        //从token获取身份信息,token代表用户输入的信息
        String name = (String)token.getPrincipal();
        //模拟从数据库中取密码
        String pwd = getPwdByUserNameFromDB(name);
        if(StringUtils.isEmpty(pwd)){
            return null;
        }
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name, pwd, this.getName());
        return simpleAuthenticationInfo;
    }
    /**
     * 模拟从数据库获取用户角色集合
     * @param name
     * @return
     */
    private Set<String> getRolesByNameFromDB(String name) {
        return roleMap.get(name);

    }

    /**
     *  模拟从数据库获取权限集合
     * @param name
     * @return
     */
    private Set<String> getPermissionsByNameFromDB(String name) {
        return permissionMap.get(name);
    }

    /**
     *  模拟从数据库获取密码
     * @param name
     * @return
     */
    private String getPwdByUserNameFromDB(String name) {
        return userInfoMap.get(name);
    }
}

 创建测试类

/**
 * @ClassName: CustomRealmTest
 * @Description:
 * @Author: Coding_wxb
 * @Date 2019.08.02 2:50
 */
public class CustomRealmTest {
    private CustomRealm customRealm = new CustomRealm();
    private DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();

    @Before
    public void init(){
        //构建环境
        defaultSecurityManager.setRealm(customRealm);
        SecurityUtils.setSecurityManager(defaultSecurityManager);
    }

    @Test
    public void testAuthentication() {
        //获取当前操作的主体
        Subject subject = SecurityUtils.getSubject();
        //用户输入的账号密码
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("woxbwo", "123");
        subject.login(usernamePasswordToken);
        //登录
        System.out.println("认证结果:"+subject.isAuthenticated());

        //拿到主体标示属性
        System.out.println("getPrincipal=" + subject.getPrincipal());
        subject.checkRole("role1");
        System.out.println("是否有对应的角色:"+subject.hasRole("role1"));
        System.out.println("是否有对应的权限:"+subject.isPermitted("video:add"));

    }
}

测试结果

认证 doGetAuthenticationInfo
认证结果:true
getPrincipal=woxbwo
权限 doGetAuthorizationInfo
权限 doGetAuthorizationInfo
是否有对应的角色:true
权限 doGetAuthorizationInfo
是否有对应的权限:false

 

posted @ 2019-08-02 02:58  xbwang520  阅读(441)  评论(0编辑  收藏  举报