【问题标题】:Apache Shiro: Exception-Handling with Multiple RealmsApache Shiro:多领域的异常处理
【发布时间】:2012-11-06 22:33:51
【问题描述】:

我们正在使用两个领域(一个用于散列密码,另一个用于生成的明文密钥) - 这按预期工作。

对于单个领域,我们可以在领域的 protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken authToken) 中引发 DisabledAccountException 异常,并在我们的应用程序中显式捕获此类异常。

现在我们有两个领域,所有异常都被 Shiro 内部捕获;所以如果一个境界失败了,也可以尝试第二个境界。但是,这种重定向只会向我们的应用程序抛出通用的AuthenticationExceptions。

是否有针对多个领域的解决方法,以便我们可以有更具体的例外情况(了解帐户是否被锁定、凭据是否完全错误……)?

【问题讨论】:

    标签: authentication shiro


    【解决方案1】:

    你需要在你的ModularRealmAuthenticator中指定你自己的AuthenticationStrategy。 ModularRealmAuthenticator 默认使用 AtLeastOneSuccessfulStrategy 并且 AtLeastOneSuccessfulStrategy 忽略异常并继续尝试使用所有可用领域登录用户。

    我们在 tynamo 项目中遇到过类似的情况,为了解决这个问题,我实现了自己的 AuthenticationStrategy,称为 FirstExceptionStrategy,它适用于多个领域和抛出它得到的第一个异常。只要每个 Token 类型只有 一个 Realm,这种方法就可以正常工作。

    实现相当简单:

    /**
     * {@link org.apache.shiro.authc.pam.AuthenticationStrategy} implementation that throws the first exception it gets
     * and ignores all subsequent realms. If there is no exceptions it works as the {@link FirstSuccessfulStrategy}
     *
     * WARN: This approach works fine as long as there is ONLY ONE Realm per Token type.
     *
     */
    public class FirstExceptionStrategy extends FirstSuccessfulStrategy {
    
        @Override
        public AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t) throws AuthenticationException {
            if ((t != null) && (t instanceof AuthenticationException)) throw (AuthenticationException) t;
            return super.afterAttempt(realm, token, singleRealmInfo, aggregateInfo, t);
        }
    
    }
    

    我再说一遍,如果每个 Token 类型有 ONLY ONE 领域,这 only 有效。

    有关我的特定场景的更多信息,请参见此处:http://jira.codehaus.org/browse/TYNAMO-154

    【讨论】:

    • 不幸的是,我们在两个领域都使用了UsernamePasswordToken,所以这并不能解决我们的问题...但是感谢您的意见!
    • 如果没有不同的 Tokens,策略将很难知道它是应该抛出异常还是应该继续查看领域列表。看看 ModularRealmAuthenticator.doMultiRealmAuthentication。也许您可以在 beforeAllAttempts 中创建自己的聚合,将异常保存在 afterAttempt 中的聚合中,然后在 afterAllAttempts 中抛出异常。
    • 感谢您的指点,但我认为这不值得。我们目前对一般例外情况很好,如果我们需要更多信息,我们会尝试您的建议。
    猜你喜欢
    • 2016-08-13
    • 2018-03-14
    • 2015-05-31
    • 2012-03-22
    • 2012-08-05
    • 1970-01-01
    • 2016-05-26
    • 2011-06-18
    • 2018-01-25
    相关资源
    最近更新 更多