SessionId/Authentication Token 生成的最佳实践

Posted

技术标签:

【中文标题】SessionId/Authentication Token 生成的最佳实践【英文标题】:Best practices for SessionId/Authentication Token generation 【发布时间】:2011-07-11 19:05:28 【问题描述】:

我见过有人使用 UUID 来生成身份验证令牌。但是,在RFC 4122 中声明

不要假设 UUID 很难猜;它们不应该被使用 作为安全能力(仅仅拥有授权的标识符 访问),例如。

我想知道,例如在 Java 和 .NET 中使用什么算法来生成 SessionId/AuthenticationToken。 UUID 是否确实不适合在具有超过平均安全需求的应用程序中用于这些目的?

【问题讨论】:

【参考方案1】:

UUID 的生成是随机的,但是熵不好的随机意味着你最终会很容易猜到UUIDs。如果您使用好的随机数生成器,您可以生成可用于会话的UUIDs。然而,问题在于UUIDs 没有内置的重放预防、篡改、固定等功能,您必须自己处理(阅读:UUID 本身不应该被认为是一个有效的会话 ID)。也就是说,这里有一个很好的 sn-p,说明如何使用 python 生成安全的 UUID

Unique session id in python

【讨论】:

【参考方案2】:

免责声明:我不是密码学家。


不要假设 UUID 很难猜;例如,它们不应该用作安全功能(仅拥有授予访问权限的标识符)。

虽然一般情况下确实如此,但还应注意,某些系统使用强加密伪随机数生成器生成 UUID(例如 Java):

public static UUID randomUUID()

用于检索类型 4(伪随机生成)UUID 的静态工厂。 UUID 是使用强加密伪随机数生成器生成的。

退货: 一个随机生成的 UUID

我想知道,例如在 Java 和 .NET 中使用什么算法来生成 SessionId/AuthenticationToken。

Tomcat 不使用 UUID 作为会话令牌,而是使用 SHA1PRNG 安全随机生成器来生成会话 ID:

/**
 * The name of the algorithm to use to create instances of
 * @link SecureRandom which are used to generate session IDs. If no
 * algorithm is specified, SHA1PRNG is used. To use the platform default
 * (which may be SHA1PRNG), specify the empty string. If an invalid
 * algorithm and/or provider is specified the @link SecureRandom instances
 * will be created using the defaults. If that fails, the @link
 * SecureRandom instances will be created using platform defaults.
 */
private String secureRandomAlgorithm = "SHA1PRNG";

这只是默认设置,您可以通过实现 org.apache.catalina.SessionIdGenerator 接口来提供自定义会话 ID 生成器。

除了在会话 ID 中使用随机生成的字符串外,标准实现还在它生成的会话 ID 中添加了 jvmRoute

此 Tomcat 实例的路由标识符。它将被添加到会话 id 以允许负载均衡器进行无状态粘性路由。 jvmRoute 如何包含在 id 中的详细信息取决于实现。有关默认行为,请参阅标准实现。

SHA1PRNG 的优势已经在here 进行过讨论。

UUID 是否确实不适用于具有高于平均安全需求的应用程序中的这些目的?

Java UUID 几乎与 Tomcat 的默认会话 ID 生成器一样安全,后者生成 16 字节长的会话 ID:

Tomcat:

/** Number of bytes in a session ID. Defaults to 16. */
private int sessionIdLength = 16;

java.util.UUID in OpenJDK 7:

public static UUID randomUUID() 
    SecureRandom ng = numberGenerator;
    if (ng == null) 
        numberGenerator = ng = new SecureRandom();
    

    byte[] randomBytes = new byte[16];
    ng.nextBytes(randomBytes);
    randomBytes[6]  &= 0x0f;  /* clear version        */
    randomBytes[6]  |= 0x40;  /* set to version 4     */
    randomBytes[8]  &= 0x3f;  /* clear variant        */
    randomBytes[8]  |= 0x80;  /* set to IETF variant  */
    return new UUID(randomBytes);

但您可以将 Tomcat 的会话 ID 生成器配置为使用超过 16 个字节以增加安全性。

延伸阅读:

https://security.stackexchange.com/a/7945/122069

【讨论】:

以上是关于SessionId/Authentication Token 生成的最佳实践的主要内容,如果未能解决你的问题,请参考以下文章