How to create a authentication token using Java

2019-02-01 08:20发布

问题:

On my Java EE6, REST service, I want to use authentication tokens for login from mobile devices, User will send their username, password and server will send back a token, which will be used to authorize the user on their further requests for a given time.

Can I simply create a token myself like this?(I guess I do not need to encrypt this since I will use HTTPS.)

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

Or there is a more standart way to create my tokens? maybe it exists in one of API's

回答1:

The scheme you are proposing effectively allows a client unlimited access to your service. After an initial login, the UID and 'userid' will be made available to the client, which can be simply combined with an always valid timestamp.

If you need a service with 'login' and a session token, then why not just use an HttpSession?



回答2:

To create a hard to guess token in Java use java.security.SecureRandom

E.g.

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

Rather than including the user name in the token it would be better to cache a user:token map in memory or in a database.  



回答3:

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

}

Taken and significantly condensed from https://stackoverflow.com/a/41156/584947



回答4:

REST is based on HTTP, and encourages using the underlying protocol rather than reinventing the wheel. HTTP uses cookies to support stateful interactions like remembering authentication, and also supports username and password authentication.

Furthermore, Java EE supports all this out of the box. Check the tutorial

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



回答5:

There is a way to create tokens which is cannot compromised but can be used for authentication too.

Create a token which is combined:

base64(username + expiration + other values for client + 3des encoded(usename, expiration, source ip, browser identitifier, other values for client))

The client can use the token to authenticate the request, for example the usage of JSON Web Token (RFC 7515).

On server side the keys which is used for 3des encoding can be rotated with time, as the token. Every request contains token for authentication and every response contains the same token or a new one before the expiration.

In that case token contains user name so on request authentication only have to check the 3des encoded part is valid or not (same as the , the source of request ip is same. In this case if somebody stole the token the usability of token is more limited as a session id. You can compose other identifiers to token, like browser etc. Harder to fake request, because the attacker have to fake more things - which is unknown for him, because he doesn't know what is on encoded part of token. (As a matter of fact there is no perfect security, only can make harder to crack)

The pros of this solution are:

  • Every piece is standard, but not the whole together and the attacker have to know the implementation details to be able to attack.
  • The client side can use parts of the token for displaying information from token while the token itself is secured because every unencrypted part is contained in encrypted part - so cannot be modified without the invalidation of token on the server side - so its easy to detect an attack.
  • There is no need of session replication / sticky sessions for clustering. The 3des keys enough to replicate between nodes - so it is suitable for stateless backend strategy.

The cons are

  • Harder to implement on server side, because for this solution have to implement the token generation / validation algorithm on server side For that server filter is recommended,.

  • The clients have to implement the store of tokens - instead of cookie browser session store is recommended - easier to stole cookies.

  • Have to make sure that the 3des keys are secured enough - Java security is recommended to use to avoid the comprimise.