Ieškojau paprasto "Java" algoritmo pseudo-atsitiktinei raidinei-skaitmeninei eilutei generuoti. Mano atveju ji būtų naudojama kaip unikalus sesijos/ rakto identifikatorius, kuris būtų unikalus per daugiau nei 500 000 kartų (mano poreikiai nereikalauja nieko sudėtingesnio).
Geriausia būtų, jei galėčiau nurodyti ilgį, priklausomai nuo unikalumo poreikių. Pavyzdžiui, sugeneruota 12 ilgio eilutė galėtų atrodyti maždaug taip: "AEYGF7K0DM1X"
.
Norėdami sugeneruoti atsitiktinę eilutę, sudurkite atsitiktinai parinktus simbolius iš priimtinų simbolių rinkinio, kol eilutė pasieks norimą ilgį.
Čia pateikiamas gana paprastas ir labai lankstus atsitiktinių identifikatorių generavimo kodas. Perskaitykite toliau pateikiamą informaciją, kurioje pateikiamos svarbios taikymo pastabos.
import java.security.SecureRandom;
import java.util.Locale;
import java.util.Objects;
import java.util.Random;
public class RandomString {
/**
* Generate a random string.
*/
public String nextString() {
for (int idx = 0; idx < buf.length; ++idx)
buf[idx] = symbols[random.nextInt(symbols.length)];
return new String(buf);
}
public static final String upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final String lower = upper.toLowerCase(Locale.ROOT);
public static final String digits = "0123456789";
public static final String alphanum = upper + lower + digits;
private final Random random;
private final char[] symbols;
private final char[] buf;
public RandomString(int length, Random random, String symbols) {
if (length < 1) throw new IllegalArgumentException();
if (symbols.length() < 2) throw new IllegalArgumentException();
this.random = Objects.requireNonNull(random);
this.symbols = symbols.toCharArray();
this.buf = new char[length];
}
/**
* Create an alphanumeric string generator.
*/
public RandomString(int length, Random random) {
this(length, random, alphanum);
}
/**
* Create an alphanumeric strings from a secure generator.
*/
public RandomString(int length) {
this(length, new SecureRandom());
}
/**
* Create session identifiers.
*/
public RandomString() {
this(21);
}
}
Sukurkite nesaugų 8 simbolių identifikatorių generatorių:
RandomString gen = new RandomString(8, ThreadLocalRandom.current());
Sukurti saugų sesijos identifikatorių generatorių:
RandomString session = new RandomString();
Sukurkite generatorių su lengvai įskaitomais kodais spausdinimui. Eilutės yra ilgesnės nei visos raidinės-skaitmeninės eilutės, kad būtų kompensuota, jog naudojama mažiau simbolių:
String easy = RandomString.digits + "ACEFGHJKLMNPQRUVWXYabcdefhijkprstuvwx";
RandomString tickets = new RandomString(23, new SecureRandom(), easy);
Generuoti sesijos identifikatorius, kurie greičiausiai bus unikalūs, nepakanka, arba galite tiesiog naudoti paprastą skaitiklį. Kai naudojami nuspėjami identifikatoriai, įsilaužėliai užgrobia sesijas.
Tarp ilgio ir saugumo tvyro įtampa. Trumpesnius identifikatorius lengviau atspėti, nes yra mažiau galimybių. Tačiau ilgesni identifikatoriai sunaudoja daugiau atminties ir pralaidumo. Didesnis simbolių rinkinys padeda, bet gali sukelti kodavimo problemų, jei identifikatoriai įtraukiami į URL adresus arba pakartotinai įvedami ranka.
Pagrindinis sesijos identifikatorių atsitiktinumo arba entropijos šaltinis turėtų būti atsitiktinių skaičių generatorius, skirtas kriptografijai. Tačiau šių generatorių inicializavimas kartais gali būti skaičiavimo požiūriu brangus arba lėtas, todėl, kai įmanoma, reikėtų stengtis juos naudoti pakartotinai.
Ne kiekvienai programai reikia saugumo. Atsitiktinis priskyrimas gali būti efektyvus būdas keliems subjektams generuoti identifikatorius bendroje erdvėje be jokio koordinavimo ar skirstymo. Koordinavimas gali būti lėtas, ypač klasterizuotoje ar paskirstytoje aplinkoje, o erdvės padalijimas sukelia problemų, kai subjektai galiausiai gauna per mažas arba per dideles dalis.
Identifikatoriai, sukurti nesiimant priemonių, kad jie taptų nenuspėjami, turėtų būti apsaugoti kitomis priemonėmis, jei užpuolikas gali turėti galimybę juos peržiūrėti ir jais manipuliuoti, kaip atsitinka daugumoje žiniatinklio programų. Turėtų būti atskira autorizavimo sistema, kuri apsaugotų objektus, kurių identifikatorių užpuolikas gali atspėti neturėdamas prieigos leidimo.
Taip pat reikia pasirūpinti, kad būtų naudojami pakankamai ilgi identifikatoriai, kad susidūrimai būtų mažai tikėtini, atsižvelgiant į numatomą bendrą identifikatorių skaičių. Tai vadinama gimtadienio paradoksu." Susidūrimo tikimybė p yra apytiksliai n2/(2qx), kur n yra faktiškai sugeneruotų identifikatorių skaičius, q yra skirtingų simbolių skaičius abėcėlėje, o x yra identifikatorių ilgis. Tai turėtų būti labai mažas skaičius, pavyzdžiui, 2‑50 arba mažesnis.
Tai apskaičiavus paaiškėja, kad susidūrimo tikimybė tarp 500 tūkst. 15 simbolių identifikatorių yra maždaug 2‑52, o tai tikriausiai mažiau tikėtina nei neaptiktos klaidos dėl kosminių spindulių ir pan.
Pagal jų specifikaciją UUID nesukurti taip, kad būtų nenuspėjami, todėl *neturėtų būti naudojami kaip sesijos identifikatoriai.
Standartinio formato UUID užima daug vietos: 36 simboliai ir tik 122 bitai entropijos. (Ne visi atsitiktinio UUID bitai parenkami atsitiktinai.) Atsitiktinai parinktoje raidinėje-skaitmeninėje eilutėje yra daugiau entropijos - tik 21 simbolis.
UUID nėra lankstūs; jie turi standartizuotą struktūrą ir išdėstymą. Tai yra jų pagrindinis privalumas ir pagrindinis trūkumas. Bendradarbiaujant su išorine šalimi UUID standartizavimas gali būti naudingas. Naudojant juos tik viduje, jie gali būti neveiksmingi.
"Java" siūlo tiesioginį būdą, kaip tai padaryti. Jei nenorite brūkšnelių, juos lengva pašalinti. Tiesiog naudokite uuid.replace("-", "")
import java.util.UUID;
public class randomStringGenerator {
public static void main(String[] args) {
System.out.println(generateString());
}
public static String generateString() {
String uuid = UUID.randomUUID().toString();
return "uuid = " + uuid;
}
}
Išvestis:
uuid = 2d7428a6-b58c-4008-8575-f05549f16316
Čia jis pateikiamas "Java" kalba:
import static java.lang.Math.round;
import static java.lang.Math.random;
import static java.lang.Math.pow;
import static java.lang.Math.abs;
import static java.lang.Math.min;
import static org.apache.commons.lang.StringUtils.leftPad
public class RandomAlphaNum {
public static String gen(int length) {
StringBuffer sb = new StringBuffer();
for (int i = length; i > 0; i -= 12) {
int n = min(12, abs(i));
sb.append(leftPad(Long.toString(round(random() * pow(36, n)), 36), n, '0'));
}
return sb.toString();
}
}
Štai pavyzdys:
scala> RandomAlphaNum.gen(42)
res3: java.lang.String = uja6snx21bswf9t89s00bxssu8g6qlu16ffzqaxxoy