Creating a strong password has never been so easy in Java when Stream API is used. Stream API is introduced in Java SE 8 and has changed the way we think and develop in Java together with the functional programming and lambda expressions. Java 9 will improve the Stream API with new convenience methods. Stream API is basically designed to work with collections in functional style. I would like to exemplify this new way of thinking simply by creating a strong password:
package com.example.java9.features; import java.security.SecureRandom; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; /** * * @author Binnur Kurt (binnur.kurt@gmail.com) */ public final class StrongPasswordApplication { private static final List<String> CHARACTER_TABLE= List.of( "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6","7","8","9", "_", "-", "$", "@", "#", "?", "%" ); public static String create(int length){ return new SecureRandom() .ints(0,CHARACTER_TABLE.size()) .limit(length) .boxed() .map( CHARACTER_TABLE::get ) .collect(Collectors.joining()); } }
There are new methods added to the Stream interface in Java 9: dropWhile, takeWhile, ofNullable. Now, we allow the application programmer to define what strong password is and create a password that conforms that definition:
package com.example.java9.features; import java.security.SecureRandom; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; /** * * @author Binnur Kurt (binnur.kurt@gmail.com) */ public class RandomPasswordApplication { private static final List<String> CHARACTER_TABLE = List.of( "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "_", "-", "$", "@", "#", "&", "%", "/", "\\", "?", "*", "+", "!", ".", ",", ";", "~", "'", "\"", "<", ">" ); public static void main(String[] args) { IntStream.range(8, 15) .boxed() .map(RandomPasswordApplication::createpassword) .map(password -> String.format("Password [length=%d] is %s", password.length(), password)) .forEach(System.out::println); } public static String createpassword(int length) { final StrongPassword strongness = new StrongPassword.Builder() .minimumNumberOfDigits(1) .minimumNumberOfSpecialCharacters(1) .minimumNumberOfCapitalLetters(1) .minimumLength(length) .build(); return new SecureRandom() .ints(0, CHARACTER_TABLE.size()) .boxed() .map(CHARACTER_TABLE::get) .takeWhile(strongness::isWeek) .collect(Collectors.joining()); } }
StrongPassword class defines the strongness of the password:
package com.example.java9.features; /** * * @author Binnur Kurt (binnur.kurt@gmail.com) */ public class StrongPassword { private final int minimumNumberOfDigits; private final int minimumNumberOfCapitalLetters; private final int minimumNumberOfSpecialCharacters; private final int minimumLength; private int length; private int numberOfDigits; private int numberOfSpecialCharacters; private int numberOfCapitalLetters; private StrongPassword(Builder builder) { this.minimumNumberOfDigits = builder.minimumNumberOfDigits; this.minimumNumberOfCapitalLetters = builder.minimumNumberOfCapitalLetters; this.minimumNumberOfSpecialCharacters = builder.minimumNumberOfSpecialCharacters; this.minimumLength = builder.minimumLength; } public boolean isWeek(String s) { final boolean isWeekPassword = (length < minimumLength) || (numberOfDigits < minimumNumberOfDigits) || (numberOfSpecialCharacters < minimumNumberOfSpecialCharacters) || (numberOfCapitalLetters < minimumNumberOfCapitalLetters); length++; if (Character.isDigit(s.charAt(0))) { numberOfDigits++; } else if (!Character.isLetter(s.charAt(0))) { numberOfSpecialCharacters++; } else if (s.equals(s.toUpperCase())) { numberOfCapitalLetters++; } return isWeekPassword; } public static class Builder { private int minimumNumberOfDigits; private int minimumNumberOfCapitalLetters; private int minimumNumberOfSpecialCharacters; private int minimumLength; public Builder minimumNumberOfDigits(int minimumNumberOfDigits) { this.minimumNumberOfDigits = minimumNumberOfDigits; return this; } public Builder minimumNumberOfCapitalLetters(int minimumNumberOfCapitalLetters) { this.minimumNumberOfCapitalLetters = minimumNumberOfCapitalLetters; return this; } public Builder minimumNumberOfSpecialCharacters(int minimumNumberOfSpecialCharacters) { this.minimumNumberOfSpecialCharacters = minimumNumberOfSpecialCharacters; return this; } public Builder minimumLength(int minimumLength) { this.minimumLength = minimumLength; return this; } public StrongPassword build() { return new StrongPassword(this); } } }
One example output of the execution is given below:
Password [length=8] is k@\D%b16 Password [length=9] is "+fORbi9f Password [length=10] is D35g,'7zKN Password [length=11] is PJTnpN~YN1o Password [length=12] is 2AD!H"xGhBZd Password [length=13] is b+A9-Ovzc+,RD Password [length=14] is *@Nj\89nW7ep5B
You could retrieve the code from this URL as NetBeans IDE Dev (Build 2017-06-14-0001) project.