如何使用Java创建身份validation令牌

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

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

String token = UUID.randomUUID().toString().toUpperCase() + "|" + "userid" + "|" + cal.getTimeInMillis(); 

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

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

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

要在Java中创建难以猜测的令牌,请使用java.security.SecureRandom

例如

 SecureRandom random = new SecureRandom(); byte bytes[] = new byte[20]; random.nextBytes(bytes); String token = bytes.toString(); 

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

REST基于HTTP,并鼓励使用底层协议而不是重新发明轮子。 HTTP使用cookie来支持有状态的交互,例如记住身份validation,还支持用户名和密码身份validation。

此外,Java EE支持所有这些开箱即用的function。 查看教程

http://docs.oracle.com/javaee/6/tutorial/doc/bncas.html

 public class SecureTokenGenerator { public static final String CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; // 2048 bit keys should be secure until 2030 - https://web.archive.org/web/20170417095741/https://www.emc.com/emc-plus/rsa-labs/historical/twirl-and-rsa-key-size.htm public static final int SECURE_TOKEN_LENGTH = 256; private static final SecureRandom random = new SecureRandom(); private static final char[] symbols = CHARACTERS.toCharArray(); private static final char[] buf = new char[SECURE_TOKEN_LENGTH]; /** * Generate the next secure random token in the series. */ public static String nextToken() { for (int idx = 0; idx < buf.length; ++idx) buf[idx] = symbols[random.nextInt(symbols.length)]; return new String(buf); } 

}

从https://stackoverflow.com/a/41156/584947获取并显着缩写

有一种创建令牌的方法,它既不会受到损害,也可以用于身份validation。

创建一个组合的令牌:

base64(用户名+到期+客户端+ 3des编码的其他值(usename,expiration,source ip,browser identitifier,客户端的其他值))

客户端可以使用令牌来validation请求,例如JSON Web Token(RFC 7515)的使用。

在服务器端,用于3des编码的密钥可以随时间旋转,作为令牌。 每个请求都包含用于身份validation的令牌,并且每个响应在到期之前包含相同的令牌或新令牌。

在这种情况下,令牌包含用户名,因此在请求身份validation时只需要检查3des编码部分是否有效(与请求ip的源相同。在这种情况下,如果有人偷了令牌,令牌的可用性更多限制为会话ID。您可以将其他标识符组合成令牌,如浏览器等。更难以伪造请求,因为攻击者必须伪造更多东西 – 这对他来说是未知的,因为他不知道编码部分是什么令牌。(事实上,没有完美的安全性,只能更难破解)

该解决方案的优点是:

  • 每个部分都是标准的,但不是整体,攻击者必须知道能够攻击的实现细节。
  • 客户端可以使用令牌的一部分来显示来自令牌的信息,而令牌本身是安全的,因为每个未加密的部分都包含在加密部分中 – 因此如果服务器端没有令牌失效就无法修改 – 因此很容易检测到攻击。
  • 不需要会话复制/粘性会话进行群集。 3des键足以在节点之间复制 – 因此它适用于无状态后端策略。

缺点是

  • 在服务器端更难实现,因为这个解决方案必须在服务器端实现令牌生成/validation算法。建议使用该服务器filter。

  • 客户端必须实现令牌存储 – 建议不要使用cookie浏览器会话存储 – 更容易窃取cookie。

  • 必须确保3des密钥足够安全 – 建议使用Java安全性来避免压缩。