WildFly:Java EE应用程序中随机加密的密码

Jen*_*gsa 4 security salt java-ee-7 wildfly-8

什么是使用存储在数据库中的随机盐渍密码的WildFly(8.2)方法?

是的实现org.jboss.crypto.digest.DigestCallback意味着有机会获得部分盐从数据库(在密码验证过程)?

或者我应该简单地将密码哈希并加密密码,然后再将其交给login方法HttpServletRequest

Sti*_*itt 5

在我看来,处理密码的'WildFly方式'就是做大多数容器所做的事情,并提供开箱即用的非安全解决方案.我不知道为什么,但到目前为止我看到的每个标准的JDBC领域实现只是在没有盐的情况下哈希密码...这是完全不安全的.

开源解决方案

编辑:我发现了一个适用于WildFly的开箱即用的解决方案.我自己最终使用它并且效果很好.我可以推荐它:

m9aertner/PBKDF2

这是我配置它的方式:

首先通过在下面创建一个文件夹将模块添加到WildFly,如下所示modules/:

C:\WildFly\v8.2.0\modules\de\rtner\PBKDF2\main

PBKDF2-1.1.0.jar文件与module.xml包含以下内容的文件一起放入其中:

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="de.rtner.PBKDF2">
  <resources>
    <resource-root path="PBKDF2-1.1.0.jar"/>
  </resources>
  <dependencies>
    <module name="org.picketbox"/>
    <module name="javax.api"/>
  </dependencies>
</module>`
Run Code Online (Sandbox Code Playgroud)

然后,将领域配置添加到standalone.xml:

<subsystem xmlns="urn:jboss:domain:security:1.2">
  <security-domains>
    <!-- .... -->

    <security-domain name="MyRealm">
      <authentication>
        <login-module code="de.rtner.security.auth.spi.SaltedDatabaseServerLoginModule" flag="required" module="de.rtner.PBKDF2">
          <module-option name="dsJndiName" value="java:/jdbc/MyDS"/>
          <module-option name="principalsQuery" value="SELECT password FROM users WHERE username = ?"/>
          <module-option name="rolesQuery" value="SELECT roles.name AS groupid, 'Roles' FROM roles INNER JOIN user_roles ON roles.name = users.username WHERE users.username = ?"/>
          <module-option name="unauthenticatedIdentity" value="guest"/>
          <!-- DEFAULT HASHING OPTIONS:
          <module-option name="hmacAlgorithm" value="HMacSHA1" />
          <module-option name="hashCharset" value="UTF-8" />
          <module-option name="formatter" value="de.rtner.security.auth.spi.PBKDF2HexFormatter" />
          <module-option name="engine" value="de.rtner.security.auth.spi.PBKDF2Engine" />
          <module-option name="engine-parameters" value="de.rtner.security.auth.spi.PBKDF2Parameters" />
          -->
        </login-module>
      </authentication>
    </security-domain>

    <!-- .... -->
  </security-domains>
</subsystem>
Run Code Online (Sandbox Code Playgroud)

SQL查询与标准相同DatabaseLoginModule.无需指定默认的散列选项(因为它们是默认值),但在创建新用户时,您需要了解它们(并正确设置它们),以便使用相同的参数正确散列其密码.

使用示例

以下是我在代码中根据给定的明文创建新密码哈希(包括salt)的方法:

public static String hash(String plainText, String storedPassword) {
    if (plainText == null) return null;
    SimplePBKDF2 crypto = new SimplePBKDF2();
    PBKDF2Parameters params = crypto.getParameters();
    params.setHashCharset("UTF-8");
    params.setHashAlgorithm("HmacSHA1");
    params.setIterationCount(1000);
    if (storedPassword != null) {
        new PBKDF2HexFormatter().fromString(params, storedPassword);
    }
    return crypto.deriveKeyFormatted(plainText);
}
Run Code Online (Sandbox Code Playgroud)

创建新密码时,您将调用此函数null作为storedPassword:

String password = hash('MySecretPassword', null);
Run Code Online (Sandbox Code Playgroud)

password 最终会看起来像这样:

"192EAEB3B7AA40B1:1000:4C137AF7AD0F3999D18E2B9E6FB726D5C07DE7D5"
Run Code Online (Sandbox Code Playgroud)

比较密码时,调用相同的函数,传递原始密码,然后比较结果:

String enteredPassword = hash(userInput, password);
if (enteredPassword.equals(password)) {
    // Ok!
}
Run Code Online (Sandbox Code Playgroud)

您需要传递原始密码的原因是哈希参数和salt存储在密码哈希中,因此算法需要存储的密码来获取这些参数并将其用于新哈希.但是,您通常不需要自己比较密码,因为这已在登录模块中完成.

或者,滚动你自己

这篇博文给出了一些关于如何推出自己添加盐的Realm实现的解释.他在GitHub上有源代码,所以也许可以使用它.

它适用于Glassfish,但我认为就Realm实现代码而言并不重要.