如何使用Java创建身份验证令牌

Spr*_*ing 24 java security authentication rest token

在我的Java EE6,REST服务上,我想使用身份验证令牌从移动设备登录,用户将发送他们的用户名,密码和服务器将发回一个令牌,这将用于授权用户他们对给定的进一步请求时间.

我可以像这样简单地创建一个令牌吗?(我想我不需要加密它,因为我将使用HTTPS.)

String token = UUID.randomUUID().toString().toUpperCase() 
            + "|" + "userid" + "|"
            + cal.getTimeInMillis();
Run Code Online (Sandbox Code Playgroud)

或者有一种更标准的方式来创建我的令牌?也许它存在于API之一中

Dan*_*aan 14

在Java中使用难以猜测的令牌 java.security.SecureRandom

例如

SecureRandom random = new SecureRandom();
byte bytes[] = new byte[20];
random.nextBytes(bytes);
String token = bytes.toString();
Run Code Online (Sandbox Code Playgroud)

不是在令牌中包含用户名,而是在内存或数据库中缓存用户:令牌映射更好.  

  • 在数组上使用字节数组和`toString`方法生成令牌可能不是一个很好的解决方案,如[here](http://stackoverflow.com/a/1536365/5078385)所述.实际上,你可以找到一个更好的解决方案[这里](http://stackoverflow.com/a/41156/5078385). (3认同)
  • @acm应用base64编码解决了这个问题 (2认同)
  • 您不应该使用“toString()”将字节标记转换为字符串。不可打印的字节将丢失,因此令牌长度将不一致。使用 Hex、Base64 或类似编码转换为可打印字符串。 (2认同)

Dmi*_*kiy 13

对于Java 8及更高版本,最快,最简单的解决方案是:

private static final SecureRandom secureRandom = new SecureRandom(); //threadsafe
private static final Base64.Encoder base64Encoder = Base64.getUrlEncoder(); //threadsafe

public static String generateNewToken() {
    byte[] randomBytes = new byte[24];
    secureRandom.nextBytes(randomBytes);
    return base64Encoder.encodeToString(randomBytes);
}
Run Code Online (Sandbox Code Playgroud)

输出示例:

wrYl_zl_8dLXaZul7GcfpqmDqr7jEnli
7or_zct_ETxJnOa4ddaEzftNXbuvNSB-
CkZss7TdsTVHRHfqBMq_HqQUxBGCTgWj
8loHzi27gJTO1xTqTd9SkJGYP8rYlNQn
Run Code Online (Sandbox Code Playgroud)

上面的代码将以32个字符的base64编码生成随机字符串。在Base64编码中,每个char编码6位数据。因此,对于上述示例中的24个字节,您将获得32个字符。您可以通过更改随机字节数来更改输出字符串的长度。此解决方案比UUID(仅使用16个随机字节)更安全,并且生成可以在HTTP url中安全使用的字符串。


ire*_*ick 8

您提出的方案有效地允许客户无限制地访问您的服务.初次登录后,UID和'userid'将可供客户端使用,可以简单地与始终有效的时间戳组合使用.

如果您需要具有"登录"和会话令牌的服务,那么为什么不使用HttpSession呢?