J'utilise une solution très simple avec Java 8. Il suffit de la personnaliser en fonction de vos besoins.
...
import java.security.SecureRandom;
...
//Generate a random String of length between 10 to 20.
//Length is also randomly generated here.
SecureRandom random = new SecureRandom();
String sampleSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
int stringLength = random.ints(1, 10, 21).mapToObj(x -> x).reduce((a, b) -> a).get();
String randomString = random.ints(stringLength, 0, sampleSet.length() - 1)
.mapToObj(x -> sampleSet.charAt(x))
.collect(Collector
.of(StringBuilder::new, StringBuilder::append,
StringBuilder::append, StringBuilder::toString));
Nous pouvons l'utiliser pour générer une chaîne alphanumérique aléatoire comme ceci (la chaîne renvoyée comportera obligatoirement des caractères non numériques ainsi que des caractères numériques) :
public String generateRandomString() {
String sampleSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_";
String sampleSetNumeric = "0123456789";
String randomString = getRandomString(sampleSet, 10, 21);
String randomStringNumeric = getRandomString(sampleSetNumeric, 10, 21);
randomString = randomString + randomStringNumeric;
//Convert String to List<Character>
List<Character> list = randomString.chars()
.mapToObj(x -> (char)x)
.collect(Collectors.toList());
Collections.shuffle(list);
//This is needed to force a non-numeric character as the first String
//Skip this for() if you don't need this logic
for(;;) {
if(Character.isDigit(list.get(0))) Collections.shuffle(list);
else break;
}
//Convert List<Character> to String
randomString = list.stream()
.map(String::valueOf)
.collect(Collectors.joining());
return randomString;
}
//Generate a random number between the lower bound (inclusive) and upper bound (exclusive)
private int getRandomLength(int min, int max) {
SecureRandom random = new SecureRandom();
return random.ints(1, min, max).mapToObj(x -> x).reduce((a, b) -> a).get();
}
//Generate a random String from the given sample string, having a random length between the lower bound (inclusive) and upper bound (exclusive)
private String getRandomString(String sampleSet, int min, int max) {
SecureRandom random = new SecureRandom();
return random.ints(getRandomLength(min, max), 0, sampleSet.length() - 1)
.mapToObj(x -> sampleSet.charAt(x))
.collect(Collector
.of(StringBuilder::new, StringBuilder::append,
StringBuilder::append, StringBuilder::toString));
}
162 votes
Méfiez-vous de le paradoxe de l'anniversaire .
62 votes
Même en tenant compte du paradoxe de l'anniversaire, si vous utilisez 12 caractères alphanumériques (62 au total), il vous faudrait encore bien plus de 34 milliards de chaînes de caractères pour atteindre le paradoxe. Et le paradoxe d'anniversaire ne garantit pas une collision de toute façon, il dit juste qu'il y a plus de 50% de chances.
6 votes
@NullUserException 50 % de chance de succès (par essai) est sacrément élevé : même avec 10 essais, le taux de succès est de 0,999. En gardant cela à l'esprit et le fait que vous pouvez essayer BEAUCOUP sur une période de 24 heures, vous n'avez pas besoin de 34 milliards de chaînes de caractères pour être pratiquement sûr de deviner au moins l'une d'entre elles. C'est la raison pour laquelle certains jetons de session doivent être très, très longs.
0 votes
Ce billet de blog devrait être utile - code pour produire des chaînes alphanumériques : rationaljava.com/2015/06/
19 votes
Ces 3 codes à une ligne sont très utiles, je suppose
Long.toHexString(Double.doubleToLongBits(Math.random()));
UUID.randomUUID().toString();
RandomStringUtils.randomAlphanumeric(12);
0 votes
La longueur n'est pas pertinente car elle dépend de l'encodage. Ce qui vous intéresse, c'est l'entropie. Une entropie de 128 bits devrait convenir à la plupart des cas d'utilisation (par exemple, 32 chiffres hexadécimaux).
25 votes
@Pijusn Je sais que c'est vieux, mais... les "50% de chance" dans le paradoxe de l'anniversaire sont... PAS "par essai", c'est "50% de chances que, sur (dans ce cas) 34 milliards de chaînes de caractères, il existe au moins une paire de doublons". Il faudrait 1,6 sept millions - 1.6e21 - d'entrées dans votre base de données pour qu'il y ait 50% de chances par essai.
1 votes
@Walt Vous avez raison, je l'ai un peu mal compris à l'époque. Mais même maintenant, je considérerais que 50% avec 36 milliards est un risque trop élevé pour une session. De plus, je ne pense pas que l'utilisation de jetons plus longs/sécurisés va introduire des problèmes significatifs.