如何在Shiro中获取多个领域的特定领域进行授权?

时间:2014-07-04 15:00:57

标签: java spring shiro

我是Spring和Shiro平台的新手。

我有两个网址集/admin/--/vendor/--。两个客户端集都使用特定领域进行身份验证。我已经扩展ModularRealmAuthenticator类来选择正确的域进行身份验证。

ModularRealmAuthenticator.java

@Override
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
    assertRealmsConfigured();
    MultiLoginAuthenticationToken mlat = null;
    Realm loginRealm = null;

    if (!(authenticationToken instanceof MultiLoginAuthenticationToken)) {
        throw new AuthenticationException("Unrecognized token , not a typeof MultiLoginAuthenticationToken ");
    } else {
        mlat = (MultiLoginAuthenticationToken) authenticationToken;
        logger.debug("realm name is : {}", mlat.getRealmName());
        loginRealm = lookupRealm(mlat.getRealmName());
    }

    return doSingleRealmAuthentication(loginRealm, mlat);

}

protected Realm lookupRealm(String realmName) throws AuthenticationException {
    Collection<Realm> realms = getRealms();
    for (Realm realm : realms) {
        if (realm.getName().equalsIgnoreCase(realmName)) {
            logger.debug("look up realm name is : {}", realm.getName());
            return realm;
        }
    }
    throw new AuthenticationException("No realm configured for Client " + realmName);
}

但是,当我将来自不同数据源集的角色和权限分配给两个客户端(管理员和供应商)时。它按照我在applicationContext.xml文件中定义的顺序迭代领域。

我的ApplicationContext.xml

<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">

    <property name="authenticator">
        <bean class="com.yatra.mp.security.MultiLoginAuthenticator"/>
    </property>

    <!-- Single realm app (realm configured next, below). If you have multiple 
        realms, use the 'realms' property instead. -->
    <property name="realms">
        <util:list>
            <ref bean="adminAuthRealm" />
            <ref bean="vendorAuthRealm" />              
        </util:list>
    </property>

    <property name="cacheManager" ref="cacheManager" />
</bean>

在两个领域都在扩展 AuthorizingRealm 类,并且都有 doGetAuthorizationInfo doGetAuthenticationInfo 方法。我在其中定义了我的自定义实现。

是否有必要扩展 ModularRealmAuthorizer 类?如果是的话,你能否告诉我我采用了哪种方法?

2 个答案:

答案 0 :(得分:1)

您可以做的是将域信息添加到您可以在AuthenticationInfo中包装的PrincipalCollection中。它是主要集合中添加的标记,在后续的shiro调用中被转移。如果它与您的领域不匹配,您可以在身份验证中使用该信息进行跳过。这实际上就是我们在自定义领域所做的事情:

public class OurRealmImpl extends AuthorizingRealm

...
    @Override
    public AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
        ... //check if user exists and read passwordhash
        Login ourLoginToken = ...
        SimplePrincipalCollection principalCollection = new SimplePrincipalCollection(ourLoginToken, realmName);
        return new SimpleAuthenticationInfo(principalCollection, passwordHash);
    }

    @Override
    public AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        Collection collection = principals.fromRealm(realmName);
        if (collection.isEmpty()) {
           return null;
        }
        Login login = (Login) collection.iterator().next();
        ... get the rights and return authorization
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addStringPermissions(permissionStrings);
        return info;
    }

答案 1 :(得分:0)

我也遇到了这个问题。最后,我解决了它。步骤如下:

1)让一个新类扩展ModularRealmAuthorizer。

#setup wp_query
$args = array(
    'posts_per_page' => $postsperpage, 
    'orderby' => array( 'rand', 'title' ),
    'order'   => 'DESC',
);

<强> 2。弹簧shiro.xml:

public class OurModularRealmAuthorizer extend ModularRealmAuthorizer{
  private map<string,OurAuthorizerRealm> mRealms;
  private map<string,OurAuthorizerRealm> getMRealms(){return mRealms;}
  private void setMRealms(map<string,OurAuthorizerRealm> mrealms){
      this.mRealms = mrealms;
      Collection<Realm> tmpRealms = new ArrayList<Realm>();

        for (OurAuthorizerRealm value : mrealms.values()) {
            Realm realm = (Realm) value;
            tmpRealms.add(realm);
        }

        this.realms = tmpRealms;/*setting realms*/
  }
}
好的。