简体   繁体   English

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

[英]How to get specific realm from Multiple realms for authorization in Shiro?

I am newbie to Spring and Shiro platforms. 我是Spring和Shiro平台的新手。

I have two url sets /admin/-- and /vendor/-- . 我有两个网址集/admin/--/vendor/-- Both client sets are authenticating with specific realms. 这两个客户端集都在特定领域进行身份验证。 I have extended ModularRealmAuthenticator class to choose correct realm for authenticating. 我扩展了ModularRealmAuthenticator类,以选择正确的领域进行身份验证。

ModularRealmAuthenticator.java 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);
}

But while I am assigning role and permissions from different set of datasource to both clients (Admin and vendor). 但是,当我将来自不同数据源集的角色和权限分配给两个客户端(管理员和供应商)时。 It is iterating the realms in order which I have defined in applicationContext.xml file. 它按照我在applicationContext.xml文件中定义的顺序来迭代领域。

My 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>

In both of realms are extending AuthorizingRealm class and both have doGetAuthorizationInfo and doGetAuthenticationInfo method. 在这两个领域中都扩展了AuthorizingRealm类,并且都具有doGetAuthorizationInfodoGetAuthenticationInfo方法。 In which I have defined my custom implementation. 在其中定义了我的自定义实现。

Is it necessary to extend ModularRealmAuthorizer class? 是否需要扩展ModularRealmAuthorizer类? If yes, could you please tell me which method I have override? 如果是,请您告诉我可以使用哪种方法?

What you can do is add the domain info to the PrincipalCollection you can wrap in the AuthenticationInfo. 您可以做的是将域信息添加到您可以包装在AuthenticationInfo中的PrincipalCollection中。 It is an added token in the principal collection that gets carried over in subsequent shiro calls. 它是主体集合中的附加令牌,该令牌在后续的shiro调用中继续使用。 You can use that info in the authentication to skip if it doesn't match your realm. 您可以在身份验证中使用该信息以跳过与您的领域不匹配的信息。 This is actually what we do in our custom realm: 这实际上是我们在自定义领域中所做的:

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;
    }

i met that problem too. 我也遇到了这个问题。 finally, i solved it. 终于,我解决了。 step as the follow: 步骤如下:

1) let a new class to extend the ModularRealmAuthorizer. 1)让新类扩展ModularRealmAuthorizer。

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*/
  }
}

2. spring-shiro.xml: 2. spring-shiro.xml:

<bean id="ourModularRealmAuthorizer" class="xx.xxx.shiro.realm.ShiroModularRealmAuthorizer">
        <property name="mRealms">
            <map>
                <entry key="ourAuthorizerRealm1" value-ref="ourAuthorizerRealm1" />
                <entry key="ourAuthorizerRealm2" value-ref="ourAuthorizerRealm2" />
            </map>
        </property>
    </bean>
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="authenticator" ref="ourModularRealmAuthenticator"></property>
        <property name="authorizer" ref="ouModularRealmAuthorizer"></property>
        <property name="cacheManager" ref="shiroCacheManager"></property>
    </bean>

all right. 好吧。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM