One neat little exercise is to generate a relatively random strings with a specific amount of certain characters. Of course you could use an Apache library for this but I think it is simple enough to do it yourself.
First of all you need to define the token set:
private static final String UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final String LOWERCASE = "abcdefghijklmnopqrstuvwxyz";
private static final String NUMBERS = "0123456789";
// https://www.owasp.org/index.php/Password_special_characters
private static final String SPECIAL = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
private static final String ALL = UPPERCASE + LOWERCASE + NUMBERS + SPECIAL;
To select random tokens from the sets we will use the SecureRandom
implementation as it is a cryptographically strong random number generator:
private static final SecureRandom random = new SecureRandom();
Then we actually select the specified amount of random tokens from a single set:
private static String selectRandomTokens(int n, String tokens) {
StringBuilder randomTokens = new StringBuilder();
for (int i = 0; i < n; i++) {
randomTokens.append(tokens.charAt(random.nextInt(tokens.length())));
}
return randomTokens.toString();
}
The API method could look like the following, providing parameters to define a minimum of tokens for each set and a maximum length:
public static String generate(int nUppercase, int nLowercase, int nNumbers, int nSpecial, int maxlength) {
int fill = maxlength - (nUppercase + nLowercase + nNumbers + nSpecial);
if (fill < 0) {
throw new IllegalArgumentException();
}
return shuffle(
selectRandomTokens(nUppercase, UPPERCASE)
+ selectRandomTokens(nLowercase, LOWERCASE)
+ selectRandomTokens(nNumbers, NUMBERS)
+ selectRandomTokens(nSpecial, SPECIAL)
+ selectRandomTokens(fill, ALL)
);
}
Finally we provide the method to shuffle the entire string:
private static String shuffle(String s) {
List<String> tokens = Arrays.asList(s.split(""));
Collections.shuffle(tokens);
return String.join("", tokens);
}
The entire code can be found on GitHub.