Tomcat 7嵌套CombinedRealm,LockoutRealm和DataSourceRealm

时间:2012-11-07 17:12:24

标签: java security tomcat realm

我正在尝试在Tomcat 7.0.32中嵌入Realms,如下所示(以伪XML形式编写):

<CombinedRealm>
  <LockoutRealm>
     <DataSourceRealm/>
  </LockoutRealm>
  <UserDatabaseRealm/>
</CombinedRealm>

这似乎不起作用 - 是否可以将Tomms中的Realms嵌套两个以上级别?我在日志中收到警告:

No rules found matching 'Server/Service/Engine/Realm/Realm/Realm'.

背后的想法是,Web服务有一些不能被锁定的关键用户(例如,作为DOS)和一些普通用户,这些用户可能拥有较弱的密码,其中lockoutRealm应该是活动的。我相信其他人一直处于这种状况。

如果还有其他方法可以实现此目的(例如LockoutRealm的白名单),请告知我们。

还需要单点登录。

我想扩展现有的LockoutRealm代码,其中包含一个永远不会被锁定的帐户列表,这是一个选项,但我不是那么热衷于编写自己的Realm,我宁愿不在该级别上添加自定义代码给Tomcat,因为这会使其他人的设置变得复杂,并且每次Tomcat更新都可能会破坏等等。

感谢您的帮助!

以下是我的测试配置的server.xml的相关部分:

<Engine name="Catalina" defaultHost="localhost">

  <Realm className="org.apache.catalina.realm.CombinedRealm">

    <!-- Lockout realm for the DB users -->
    <Realm className="org.apache.catalina.realm.LockOutRealm">
      <!-- PRIMARY: DataSourceRealm with user DB -->
      <Realm className="org.apache.catalina.realm.DataSourceRealm"
         dataSourceName="jdbc/authority"
         userTable="user" userNameCol="username" 
         userCredCol="password" digest="SHA"
         userRoleTable="user_role" roleNameCol="rolename" />
    </Realm>

    <!-- FALLBACK:
         This Realm uses the UserDatabase configured in the global JNDI
         resources under the key "UserDatabase".  Any edits
         that are performed against this UserDatabase are immediately
         available for use by the Realm.  -->
    <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
           resourceName="UserDatabase"/>

  </Realm>

  <Host name="localhost"  appBase="webapps"
        unpackWARs="true" autoDeploy="true">

    <!-- SingleSignOn valve, share authentication between web applications
         Documentation at: /docs/config/valve.html -->
    <Valve className="org.apache.catalina.authenticator.SingleSignOn" />

    <!-- Access log processes all example.
         Documentation at: /docs/config/valve.html
         Note: The pattern used is equivalent to using pattern="common" -->
    <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
           prefix="localhost_access_log." suffix=".txt"
           pattern="%h %l %u %t &quot;%r&quot; %s %b" />

  </Host>
</Engine>

2 个答案:

答案 0 :(得分:3)

Apache commons-digester用于解析配置文件,所以我怀疑这个特殊用例并不是预期的。

对于org.apache.catalina.startup.RealmRuleSet.addRuleInstances配置,Tomcat的Realm似乎只能进行2级深度操作。看起来很简单,可以在那里添加另一层。

我必须查看如何配置浏览器以查看是否可以支持任意级别,或者是否必须手动配置某个子集。

随意转到Tomcat users' list请求进行此类更改。

答案 1 :(得分:3)

现在的新答案是:

更新到Tomcat 7.0.33或更高版本。然后它完美运行。

Christopher Schultz非常友好地将我的问题转发给Tomcat用户列表。伟大的Tomcat开发人员已经立即解决了这个问题并将其放入下一个版本中。非常感谢!

所以你现在可以使用像问题中那样的结构,或者像这样使用不同的顺序/“优先级”:

...

<Engine name="Catalina" defaultHost="localhost">

  <Realm className="org.apache.catalina.realm.CombinedRealm">

    <!-- PRIMARY: tomcat-users.xml with critical system users
                  that should always work, DB independent and without lockout
                  NOTE: If the wrong password is given, the secondary path with
                        lockout is still attempted, so that a lockout on that path
                        will still occur and be logged. Still the primary path is not 
                        locked for access by that happening.                           -->
    <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
           resourceName="UserDatabase"/>

    <!-- SECONDARY: DataSourceRealm with DB with lockout functionality -->
    <!-- (three level nesting of realms requires Tomcat >= 7.0.33)     -->
    <Realm className="org.apache.catalina.realm.LockOutRealm" 
      failureCount="5" lockOutTime="60" > <!-- note that when an account is locked correct password
                                               login is no longer possible (would otherwise defeat purpose of lockout),
                                               but also lockoutTime is still reset in each correct attempt -->

      <Realm className="org.apache.catalina.realm.DataSourceRealm"
         dataSourceName="jdbc/authority"
         userTable="user" userNameCol="username" 
         userCredCol="password" digest="SHA"
         userRoleTable="user_role" roleNameCol="rolename" />

    </Realm>

  </Realm>

  <Host >

    ...

  </Host>
</Engine>

...

当然,您也可以使用其他领域和其他组合。

请注意,在日志中有一点可能会产生误导:在这种结构中,如果为主域中存储的一个关键用户提供了错误的密码,则主域拒绝访问,然后通过锁定域拒绝次域尝试并拒绝访问最终锁定用户名。锁定领域将其记录为警告“已尝试对锁定的用户进行身份验证...”。仍然使用正确的密码,访问通过主域继续工作,因为它不通过锁定领域。即一切按预期工作,只是日志信息可能导致混淆(当然这是不可避免的)。