嵌套在 LockoutRealm 中时如何在 Java 中获取 Tomcat CredentialHandler

2023-12-23

我正在使用 Tomcat 8.5.59 并在 context.xml 中有以下领域:

<Realm className="org.apache.catalina.realm.LockOutRealm" >
    <Realm className="org.apache.catalina.realm.DataSourceRealm" dataSourceName="jdbc/MyName" localDataSource="true">
      <CredentialHandler className="org.apache.catalina.realm.NestedCredentialHandler">
        <CredentialHandler className="org.apache.catalina.realm.SecretKeyCredentialHandler" />
        <CredentialHandler className="org.apache.catalina.realm.MessageDigestCredentialHandler" algorithm="SHA-512" />
      </CredentialHandler>
    </Realm>
</Realm>

我想在我的 Java 应用程序中使用 CredentialHandler 来散列和存储密码。根据克里斯托弗·舒尔茨 (Christopher Schultz) 的演讲http://people.apache.org/~schultz/ApacheCon%20NA%202016/Seamless%20Upgrades%20for%20Credential%20Security%20in%20Apache%20Tomcat.pdf http://people.apache.org/%7Eschultz/ApacheCon%20NA%202016/Seamless%20Upgrades%20for%20Credential%20Security%20in%20Apache%20Tomcat.pdf我是这样理解的:

CredentialHandler ch = (CredentialHandler) application.getAttribute(Globals.CREDENTIAL_HANDLER);

问题是它返回一个空白/默认凭证处理程序,而不是我配置的凭证处理程序。

如果我删除 LockoutRealm 定义,它会正常工作,因此似乎有一个嵌套领域(LockoutRealm、DataSourceRealm)会导致它失败。翻看Tomcat代码,好像是调用的代码setAttribute(Globals.CREDENTIAL_HANDLER)不需要CombinedRealm考虑到。

如何在我的应用程序中获取配置的凭据处理程序,以便我可以调用 .matches() 和 .mutate() 方法? 我宁愿不删除锁定领域,因为这会损害安全性。


Edit:

此用例很常见:应用程序必须能够将变异的密码保存到数据库中,以便在用户登录时 tomcat 可以对其进行基于表单的身份验证。每次创建新的用户帐户时,用户的密码必须进行变异并保存到数据库中。

此外,当用户想要更改密码时,表单会询问当前密码和新密码 - .matches() 用于确认“当前”密码与现有密码匹配,然后再将其更改为新密码(这又是必须突变)。

使用上下文中定义的凭证处理程序对于确保密码按照 tomcat 所需的确切方式进行变异非常重要。另一种方法是为每个应用程序提供自己相应的库,鉴于 tomcat 已经拥有它们,这似乎很浪费且容易出错。

这一切都在我的问题开头的克里斯托弗·舒尔茨的链接中进行了描述。

我认为这都是相当标准的,Tomcat 提供了CredentialHandler ch = (CredentialHandler) application.getAttribute(Globals.CREDENTIAL_HANDLER)以此目的。问题是该实现没有考虑使用 LockoutRealm - 它假设凭证处理程序是直接在顶级领域下定义的,所以我想知道这是否是 tomcat 中的监督/错误,或者它是否像那样工作通过设计,如果有某种方式我可以访问定义的 .mutate() 和 .matches() 函数CredentialHandler同时还使用LockOutRealm.

另外,tomcat曾经提供RealmBase.Digest(String credentials, String algorithm, String encoding)对于这个用例,但该方法在 8.5 中已弃用并在 9 中删除,所以我明白CredentialHandler ch = (CredentialHandler) application.getAttribute(Globals.CREDENTIAL_HANDLER)这是我们应该采取的新方式。


Edit 2:

getAttribute(Globals.CREDENTIAL_HANDLER)返回默认值CredentialHandler这根本不加密密码。调试器显示该类是StandardContext。单步执行代码,一切似乎都是正确的,但它并没有深入到DataSourceRealm得到定义的NestedCredentialHandler,相反,它着眼于LockoutRealm,没有找到直系子代CredentialHandler,因此创建并返回一个默认值。我相信这是记录在https://tomcat.apache.org/tomcat-8.5-doc/config/credentialhandler.html https://tomcat.apache.org/tomcat-8.5-doc/config/credentialhandler.html:

CredentialHandler 元素必须嵌套在 Realm 组件内。如果未包含,则将使用 MessageDigestCredentialHandler 创建默认的 CredentialHandler。


简单的答案是您需要配置一个相同的(或操作上相同的)CredentialHandler在 LockOutRealm 上。

(很抱歉我两年前没有看到这个问题!)

因为你从来没有打算创建new密码使用SHA-512(您希望始终编写使用 PBKDF2 的新凭证,对吗?),您可以执行以下操作:

<Realm className="org.apache.catalina.realm.LockOutRealm" >
    <Realm className="org.apache.catalina.realm.DataSourceRealm" dataSourceName="jdbc/MyName" localDataSource="true">
      <!--
        Define a CredentialHandler which will be used
        exclusively by the container. See below for one that
        can be used by the application.

        This repeated-configuration is necessary because of the
        use of the LockOutRealm, which hides the CredentialHandler
        defined on the "real realm" from its parent.
      -->
      <CredentialHandler className="org.apache.catalina.realm.NestedCredentialHandler">
        <CredentialHandler className="org.apache.catalina.realm.SecretKeyCredentialHandler" />
        <CredentialHandler className="org.apache.catalina.realm.MessageDigestCredentialHandler" algorithm="SHA-512" />
      </CredentialHandler>
    </Realm>
    <!--
      Repeat the NestedCredentialHandler for the benefit of the
      LockOutRealm, which would otherwise have an empty/default
      CredentialHandler whish is not useful to the application.

      This allows the application to obtain a CredentialHandler
      which can be used to both verify existing user credentials
      as well as generate new stored-credentials.

      This must be a copy of the NestedCredentialHandler above,
      in order to both allow verification of existing user
      credentials (using #matches(), which will try all possible
      nested CredentialHandlers) as well as the generation of
      new stored credentials (using #mutate(), which will only
      use the first-defined aka primary CredentialHandler.
      -->
    <CredentialHandler className="org.apache.catalina.realm.NestedCredentialHandler">
      <CredentialHandler className="org.apache.catalina.realm.SecretKeyCredentialHandler" />
      <CredentialHandler className="org.apache.catalina.realm.MessageDigestCredentialHandler" algorithm="SHA-512" />
    </CredentialHandler>
</Realm>

最里面的CredentialHandler将在登录期间用于实际检查您的凭据是否匹配,而最外面的CredentialHandler当您想在应用程序中更改自己的版本时,将使用它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌套在 LockoutRealm 中时如何在 Java 中获取 Tomcat CredentialHandler 的相关文章

  • 如何让 BlazeDS 忽略属性?

    我有一个 java 类 它有一个带有 getter 和 setter 的字段 以及第二对 getter 和 setter 它们以另一种方式访问 该字段 public class NullAbleId private static final
  • 在 Java 中克隆对象 [3 个问题]

    这样做会调用Asub的clone方法吗 或者Asub深度克隆是否正确 如果没有的话 有没有办法通过这种方法对Asub进行深度克隆呢 abstract class Top extends TopMost protected Object cl
  • 序列的排列?

    我有具体数量的数字 现在我想以某种方式显示这个序列的所有可能的排列 例如 如果数字数量为3 我想显示 0 0 0 0 0 1 0 0 2 0 1 0 0 1 1 0 1 2 0 2 0 0 2 1 0 2 2 1 0 0 1 0 1 1 0
  • Spring应用中Eureka健康检查的问题

    我正在开发一个基于 Spring 的应用程序 其中包含多个微服务 我的一个微服务充当尤里卡服务器 到目前为止一切正常 在我所有其他微服务中 用 EnableEurekaClient 我想启用这样的健康检查 应用程序 yml eureka c
  • 在内存中使用 byte[] 创建 zip 文件。 Zip 文件总是损坏

    我创建的 zip 文件有问题 我正在使用 Java 7 我尝试从字节数组创建一个 zip 文件 其中包含两个或多个 Excel 文件 应用程序始终完成 没有任何异常 所以 我以为一切都好 当我尝试打开 zip 文件后 Windows 7 出
  • 如何循环遍历所有组合,例如48 选择 5 [重复]

    这个问题在这里已经有答案了 可能的重复 如何在java中从大小为n的集合中迭代生成k个元素子集 https stackoverflow com questions 4504974 how to iteratively generate k
  • .properties 中的通配符

    是否存在任何方法 我可以将通配符添加到属性文件中 并且具有所有含义 例如a b c d lalalala 或为所有以结尾的内容设置一个正则表达式a b c anything 普通的 Java 属性文件无法处理这个问题 不 请记住 它实际上是
  • 如何在 Spring 中禁用使用 @Component 注释创建 bean?

    我的项目中有一些用于重构逻辑的通用接口 它看起来大约是这样的 public interface RefactorAwareEntryPoint default boolean doRefactor if EventLogService wa
  • 如何获取之前的URL?

    我需要调用我的网络应用程序的 URL 例如 如果有一个从 stackoverflow com 到我的网站 foo com 的链接 我需要 Web 应用程序 托管 bean 中的 stackoverflow 链接 感谢所有帮助 谢谢 并不总是
  • 在 Jar 文件中运行 ANT build.xml 文件

    我需要使用存储在 jar 文件中的 build xml 文件运行 ANT 构建 该 jar 文件在类路径中可用 是否可以在不分解 jar 文件并将 build xml 保存到本地目录的情况下做到这一点 如果是的话我该怎么办呢 Update
  • 如何更改javaFX中按钮的图像?

    我正在使用javaFX 我制作了一个按钮并为此设置了图像 代码是 Image playI new Image file c Users Farhad Desktop icons play2 jpg ImageView iv1 new Ima
  • 在 junit 测试中获取 javax.lang.model.element.Element 类

    我想测试我的实用程序类 ElementUtils 但我不知道如何将类作为元素获取 在 AnnotationProcessors 中 我使用以下代码获取元素 Set
  • 像 Java 这样的静态类型语言中动态方法解析背后的原因是什么

    我对 Java 中引用变量的动态 静态类型和动态方法解析的概念有点困惑 考虑 public class Types Override public boolean equals Object obj System out println i
  • volatile、final 和synchronized 安全发布的区别

    给定一个带有变量 x 的 A 类 变量 x 在类构造函数中设置 A x 77 我们想将 x 发布到其他线程 考虑以下 3 种变量 x 线程安全 发布的情况 1 x is final 2 x is volatile 3 x 设定为同步块 sy
  • tomcat 中受密码保护的应用程序

    我正在使用 JSP Servlet 开发一个Web应用程序 并且我使用了Tomcat 7 0 33 as a web container 所以我的要求是tomcat中的每个应用程序都会password像受保护的manager applica
  • 为什么 Java 8 不允许非公共默认方法?

    让我们举个例子 public interface Testerface default public String example return Hello public class Tester implements Testerface
  • 关键字“table”附近的语法不正确,无法提取结果集

    我使用 SQL Server 创建了一个项目 其中包含以下文件 UserDAO java public class UserDAO private static SessionFactory sessionFactory static se
  • 专门针对 JSP 的测试驱动开发

    在理解 TDD 到底是什么之前 我就已经开始编写测试驱动的代码了 在没有实现的情况下调用函数和类可以帮助我以更快 更有效的方式理解和构建我的应用程序 所以我非常习惯编写代码 gt 编译它 gt 看到它失败 gt 通过构建其实现来修复它的过程
  • Android:无法使用 DbHelper 和 Contract 类将数据插入 SQLite

    public class Main2Activity extends AppCompatActivity private EditText editText1 editText2 editText3 editText4 private Bu
  • 包 javax.el 不存在

    我正在使用 jre6 eclipse 并导入 javax el 错误 包 javax el 不存在 javac 导入 javax el 过来 这不应该是java的一部分吗 谁能告诉我为什么会这样 谢谢 米 EL 统一表达语言 是 Java

随机推荐