Generer en sikker tilfældig adgangskode i Java
Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:
>> KONTROLLER KURSEN1. Introduktion
I denne vejledning ser vi på forskellige metoder, vi kan bruge til at generere en sikker tilfældig adgangskode i Java.
I vores eksempler genererer vi adgangskoder med ti tegn, hver med mindst to små bogstaver, to store bogstaver, to cifre og to specialtegn.
2. Brug af Passay
Passay er et håndhævelsesbibliotek til adgangskodepolitik. Især kan vi gøre brug af biblioteket til at generere adgangskoden ved hjælp af et konfigurerbart regelsæt.
Ved hjælp af standard CharacterData implementeringer, kan vi formulere de nødvendige regler for adgangskoden. Desuden kan vi formulere brugerdefineret CharacterData implementeringer, der passer til vores krav: Her har vi oprettet en brugerdefineret CharacterData implementering af specialtegn. Dette giver os mulighed for at begrænse det sæt gyldige tegn, der er tilladt. Bortset fra det bruger vi standardimplementeringer af CharacterData for vores andre regler. Lad os nu kontrollere vores generator mod en enhedstest. For eksempel kan vi kontrollere tilstedeværelsen af to specialtegn: Det er værd at bemærke det selvom Passay er open source, er det dobbelt licenseret under både LGPL og Apache 2. Som med enhver tredjepartssoftware skal vi være sikre på at overholde disse licenser, når vi bruger den i vores produkter. GNU-webstedet har flere oplysninger om LGPL og Java. Lad os derefter se på RandomStringGenerator i Apache Commons-tekst. Med RandomStringGenerator, Vi kan generere Unicode-strenge, der indeholder det specificerede antal kodepunkter. Nu opretter vi en forekomst af generatoren ved hjælp af RandomStringGenerator.Builder klasse. Selvfølgelig kan vi også manipulere generatorens egenskaber yderligere. Med hjælp fra bygherren kan vi nemt ændre standardimplementeringen af tilfældighed. Desuden kan vi også definere de tegn, der er tilladt i strengen: Nu, en begrænsning af brugen RandomStringGenerator er det det mangler evnen til at specificere antallet af tegn i hvert sæt, som i Passay. Vi kan dog omgå det ved at flette resultaterne af flere sæt: Lad os derefter validere den genererede adgangskode ved at kontrollere små bogstaver: Som standard, RandomStringGenerator gør brug af ThreadLocalRandom for tilfældighed. Nu er det vigtigt at nævne at dette ikke sikrer kryptografisk sikkerhed. Vi kan dog indstille kilden til tilfældighed ved hjælp af usingRandom (TextRandomProvider). For eksempel kan vi gøre brug af SecureTextRandomProvider til kryptografisk sikkerhed: En anden mulighed, som vi kunne benytte, er RandomStringUtils klasse i Apache Commons Lang-biblioteket. Denne klasse udsætter flere statiske metoder, som vi kan bruge til vores problemangivelse. Lad os se, hvordan vi kan give det udvalg af kodepunkter, der er acceptabelt for adgangskoden: Lad os kontrollere antallet af numeriske tegn for at validere den genererede adgangskode: Her, RandomStringUtils gør brug af Tilfældig som standard som tilfældighedskilde. Der er dog en metode i biblioteket, der lader os specificere kilden til tilfældighed: Nu kunne vi sikre kryptografisk sikkerhed ved hjælp af en forekomst af SecureRandom. Denne funktionalitet kan dog ikke udvides til andre metoder i biblioteket. På en sidebemærkning, Apache går ind for brugen af RandomStringUtils kun til enkel brug. Vi kan også gøre brug af SecureRandom klasse for at oprette en brugerdefineret hjælpeklasse til vores scenario. For det første, lad os generere en streng med specialtegn i længde to: Bemærk også det 33 og 45 angive rækkevidden af Unicode-tegn. Nu kan vi generere flere streams i henhold til vores krav. Derefter kan vi flette resultatsættene for at generere den krævede adgangskode: Lad os nu validere den genererede adgangskode for antallet af specialtegn: I denne vejledning var vi i stand til at generere adgangskoder, der svarede til vores krav, ved hjælp af forskellige biblioteker. Som altid er kodeeksemplerne, der bruges i artiklen, tilgængelige på GitHub.offentlig streng genererePassayPassword () {PasswordGenerator gen = ny PasswordGenerator (); CharacterData lowerCaseChars = EnglishCharacterData.LowerCase; CharacterRule lowerCaseRule = ny CharacterRule (lowerCaseChars); lowerCaseRule.setNumberOfCharacters (2); CharacterData upperCaseChars = EnglishCharacterData.UpperCase; CharacterRule upperCaseRule = ny CharacterRule (upperCaseChars); upperCaseRule.setNumberOfCharacters (2); CharacterData digitChars = EnglishCharacterData.Digit; CharacterRule digitRule = ny CharacterRule (digitChars); digitRule.setNumberOfCharacters (2); CharacterData specialChars = new CharacterData () {public String getErrorCode () {return ERROR_CODE; } offentlige String getCharacters () {return "[email protected] # $% ^ & * () _ +"; }}; CharacterRule splCharRule = ny CharacterRule (specialChars); splCharRule.setNumberOfCharacters (2); Strengadgangskode = gen.generatePassword (10, splCharRule, lowerCaseRule, upperCaseRule, digitRule); returnere adgangskode }
@Test offentlig ugyldig nårPasswordGeneratedUsingPassay_thenSuccessful () {RandomPasswordGenerator passGen = ny RandomPasswordGenerator (); Strengadgangskode = passGen.generatePassayPassword (); int specialCharCount = 0; for (char c: password.toCharArray ()) hvis (c> = 33
3. Brug RandomStringGenerator
public String generateRandomSpecialCharacters (int length) {RandomStringGenerator pwdGenerator = new RandomStringGenerator.Builder (). withinRange (33, 45) .build (); returner pwdGenerator.generate (længde); }
offentlig streng generereCommonTextPassword () {String pwString = createRandomSpecialCharacters (2) .concat (generateRandomNumbers (2)) .concat (generateRandomAlphabet (2, true)) .concat (generateRandomAlphabet (2, false)) .concat (generere 2) Liste pwChars = pwString.chars () .mapToObj (data -> (char) data) .collect (Collectors.toList ()); Collections.shuffle (pwChars); String password = pwChars.stream () .collect (StringBuilder :: new, StringBuilder :: append, StringBuilder :: append) .toString (); returnere adgangskode; }
@Test offentlig ugyldig nårPasswordGeneratedUsingCommonsText_thenSuccessful () {RandomPasswordGenerator passGen = ny RandomPasswordGenerator (); Strengadgangskode = passGen.generateCommonTextPassword (); int lavereCaseCount = 0; for (char c: password.toCharArray ())
offentlig streng generere RandomSpecialCharacters (int længde) {SecureTextRandomProvider stp = ny SecureTextRandomProvider (); RandomStringGenerator pwdGenerator = ny RandomStringGenerator.Builder () .withinRange (33, 45) .usingRandom (stp) .build (); returner pwdGenerator.generate (længde); }
4. Brug RandomStringUtils
public String createCommonLangPassword () {String upperCaseLetters = RandomStringUtils.random (2, 65, 90, true, true); String lowerCaseLetters = RandomStringUtils.random (2, 97, 122, true, true); Strengnumre = RandomStringUtils.randomNumeric (2); String specialChar = RandomStringUtils.random (2, 33, 47, false, false); String totalChars = RandomStringUtils.randomAlphanumeric (2); String combinedChars = upperCaseLetters.concat (lowerCaseLetters) .concat (tal) .concat (specialChar) .concat (totalChars); Liste pwdChars = combinedChars.chars () .mapToObj (c -> (char) c) .collect (Collectors.toList ()); Collections.shuffle (pwdChars); String password = pwdChars.stream () .collect (StringBuilder :: new, StringBuilder :: append, StringBuilder :: append) .toString (); returnere adgangskode }
@Test offentlig ugyldig nårPasswordGeneratedUsingCommonsLang3_thenSuccessful () {RandomPasswordGenerator passGen = ny RandomPasswordGenerator (); Strengadgangskode = passGen.generateCommonsLang3Password (); int numCount = 0; for (char c: password.toCharArray ())
String lowerCaseLetters = RandomStringUtils. tilfældig (2, 97, 122, sand, sand, null, ny SecureRandom ());
5. Brug af en brugerdefineret værktøjsmetode
public Stream getRandomSpecialChars (int count) {Tilfældig tilfældig = ny SecureRandom (); IntStream specialChars = random.ints (count, 33, 45); returnere specialChars.mapToObj (data -> (char) data); }
offentlig streng generereSecureRandomPassword () {Stream pwdStream = Stream.concat (getRandomNumbers (2), Stream.concat (getRandomSpecialChars (2), Stream.concat (getRandomAlphabets (2, true), getRandomAlphabets (4, false)))); Liste charList = pwdStream.collect (Collectors.toList ()); Collections.shuffle (charList); String password = charList.stream () .collect (StringBuilder :: new, StringBuilder :: append, StringBuilder :: append) .toString (); returnere adgangskode }
@Test offentlig ugyldig nårPasswordGeneratedUsingSecureRandom_thenSuccessful () {RandomPasswordGenerator passGen = ny RandomPasswordGenerator (); Strengadgangskode = passGen.generateSecureRandomPassword (); int specialCharCount = 0; for (char c: password.toCharArray ()) c = 2);
6. Konklusion
Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:
>> KONTROLLER KURSEN