【问题标题】:How to get specific realm from Multiple realms for authorization in Shiro?如何从多个领域中获取特定领域以在 Shiro 中进行授权?
【发布时间】:2014-08-25 22:50:42
【问题描述】:

我是 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 类,并且都具有 doGetAuthorizationInfodoGetAuthenticationInfo 方法。我在其中定义了我的自定义实现。

是否需要扩展 ModularRealmAuthorizer 类?如果是,你能告诉我我覆盖了哪种方法吗?

【问题讨论】:

  • 不清楚您的实际问题是什么。
  • 您好 Wouter,我的问题是:我的应用程序中有两种类型的用户(管理员和供应商)。两种类型的用户都使用两个表进行身份验证,并且都具有不同的权限,这些权限是使用来自同一数据库的不同表进行授权的。我正在为扩展 AuthorizingRealm 类的两种类型的用户使用两个领域进行身份验证和授权。我在上面写了自定义身份验证器,它调用正确的领域进行身份验证。但是在进行授权时,它调用了错误的领域
  • (即领域正在按照我们在 applicationContext.xml 文件中定义的顺序执行授权)。所以我的问题是如何调用正确的领域来授权特定用户?因为两个领域都有 doGetAuthenticationInfo 方法来将角色和权限分配给特定类型的用户。如果您对此有任何其他问题,请告诉我。我从几天开始就陷入了这个问题。请帮助我。提前致谢。

标签: java spring shiro


【解决方案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;
    }

【讨论】:

  • 嗨,Wouter,谢谢一百万。我在两个领域都覆盖了“支持”方法。这就是为什么我能够调用正确的领域进行身份验证。但我不明白为什么它没有被要求授权..你能告诉我原因吗?
  • 我在两个领域都添加了以下代码:code @Override public boolean supports(AuthenticationToken token) { if (token instanceof MultiLoginAuthenticationToken) { return ((MultiLoginAuthenticationToken)token).getRealmName().equalsIgnoreCase("AdminAuthRealm"); } return false; }
  • 嗨,Wouter,我已经阅读了 Shiro 的文章。根据我理解的概念,支持仅用于身份验证的方法,而不是用于授权的方法。就我而言,身份验证工作正常。我在授权过程中遇到问题。请让我知道我该怎么处理这个问题?谢谢。
  • 完全误解了这个问题。我已将答案更改为希望您在问。抱歉耽搁了。
【解决方案2】:

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

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:

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

好的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-01
    • 1970-01-01
    • 2017-10-27
    • 2012-08-03
    • 2016-03-12
    • 2015-01-19
    • 2016-03-31
    • 2016-08-13
    相关资源
    最近更新 更多