代码之家  ›  专栏  ›  技术社区  ›  Jens Piegsa

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

  •  4
  • Jens Piegsa  · 技术社区  · 9 年前

    WildFly(8.2)如何处理存储在数据库中的随机加密密码?

    org.jboss.crypto.digest.DigestCallback (在密码验证过程中)是否意味着可以从数据库访问salt部分?

    或者我应该在将密码交给 login 方法 HttpServletRequest ?

    1 回复  |  直到 9 年前
        1
  •  5
  •   Stijn de Witt    8 年前

    在我看来,处理密码的“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>`
    

    然后,将领域配置添加到 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>
    

    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);
    }
    

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

    String password = hash('MySecretPassword', null);
    

    password 最终看起来像这样:

    "192EAEB3B7AA40B1:1000:4C137AF7AD0F3999D18E2B9E6FB726D5C07DE7D5"
    

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

    String enteredPassword = hash(userInput, password);
    if (enteredPassword.equals(password)) {
        // Ok!
    }
    

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

    或者,自己动手

    This blog post 给出了一些关于如何滚动自己的Realm实现的解释,该实现确实添加了盐。他有 source code on GitHub 所以也许可以用这个。

    这是针对Glassfish的,但我认为这与Realm实现代码无关。