Generer en sikker tilfældig adgangskode i Java

Java Top

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

1. 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:

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 }

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:

@Test offentlig ugyldig nårPasswordGeneratedUsingPassay_thenSuccessful () {RandomPasswordGenerator passGen = ny RandomPasswordGenerator (); Strengadgangskode = passGen.generatePassayPassword (); int specialCharCount = 0; for (char c: password.toCharArray ()) hvis (c> = 33 

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.

3. Brug RandomStringGenerator

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:

public String generateRandomSpecialCharacters (int length) {RandomStringGenerator pwdGenerator = new RandomStringGenerator.Builder (). withinRange (33, 45) .build (); returner pwdGenerator.generate (længde); } 

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:

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

Lad os derefter validere den genererede adgangskode ved at kontrollere små bogstaver:

@Test offentlig ugyldig nårPasswordGeneratedUsingCommonsText_thenSuccessful () {RandomPasswordGenerator passGen = ny RandomPasswordGenerator (); Strengadgangskode = passGen.generateCommonTextPassword (); int lavereCaseCount = 0; for (char c: password.toCharArray ()) 

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:

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

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:

 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 }

Lad os kontrollere antallet af numeriske tegn for at validere den genererede adgangskode:

@Test offentlig ugyldig nårPasswordGeneratedUsingCommonsLang3_thenSuccessful () {RandomPasswordGenerator passGen = ny RandomPasswordGenerator (); Strengadgangskode = passGen.generateCommonsLang3Password (); int numCount = 0; for (char c: password.toCharArray ()) 

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:

String lowerCaseLetters = RandomStringUtils. tilfældig (2, 97, 122, sand, sand, null, ny SecureRandom ());

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.

5. Brug af en brugerdefineret værktøjsmetode

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:

public Stream getRandomSpecialChars (int count) {Tilfældig tilfældig = ny SecureRandom (); IntStream specialChars = random.ints (count, 33, 45); returnere specialChars.mapToObj (data -> (char) data); }

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:

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 } 

Lad os nu validere den genererede adgangskode for antallet af specialtegn:

@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

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.

Java bund

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

$config[zx-auto] not found$config[zx-overlay] not found