diff --git a/java-strings/pom.xml b/java-strings/pom.xml
index b1ba49b33a..a43490ce5c 100644
--- a/java-strings/pom.xml
+++ b/java-strings/pom.xml
@@ -68,7 +68,17 @@
emoji-java
4.0.0
-
+
+
+ org.passay
+ passay
+ 1.3.1
+
+
+ org.apache.commons
+ commons-text
+ 1.4
+
diff --git a/java-strings/src/test/java/com/baeldung/string/password/StringPasswordUnitTest.java b/java-strings/src/test/java/com/baeldung/string/password/StringPasswordUnitTest.java
new file mode 100644
index 0000000000..ac610aee6f
--- /dev/null
+++ b/java-strings/src/test/java/com/baeldung/string/password/StringPasswordUnitTest.java
@@ -0,0 +1,198 @@
+package com.baeldung.string.password;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.security.SecureRandom;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.text.RandomStringGenerator;
+import org.junit.Test;
+import org.passay.CharacterData;
+import org.passay.CharacterRule;
+import org.passay.EnglishCharacterData;
+import org.passay.PasswordGenerator;
+
+/**
+ * Examples of passwords conforming to various specifications, using different libraries.
+ *
+ *
+ * @author tritty
+ *
+ */
+public class StringPasswordUnitTest {
+ /**
+ * Special characters allowed in password.
+ */
+ public static final String ALLOWED_SPL_CHARACTERS = "!@#$%^&*()_+";
+
+ public static final String ERROR_CODE = "ERRONEOUS_SPECIAL_CHARS";
+
+ Random random = new SecureRandom();
+
+ /**
+ * Password generated using Passay with minimum of 2 lowercase, 2 uppercase, 2 numbers and 2 special characters.
+ *
+ */
+ @Test
+ public void whenPasswordGeneratedUsingPassay_thenSuccessful() {
+ PasswordGenerator gen = new PasswordGenerator();
+ CharacterData lowerCaseChars = EnglishCharacterData.LowerCase;
+ CharacterRule lowerCaseRule = new CharacterRule(lowerCaseChars);
+ lowerCaseRule.setNumberOfCharacters(2);
+ CharacterData upperCaseChars = EnglishCharacterData.UpperCase;
+ CharacterRule upperCaseRule = new CharacterRule(upperCaseChars);
+ upperCaseRule.setNumberOfCharacters(2);
+ CharacterData digitChars = EnglishCharacterData.Digit;
+ CharacterRule digitRule = new CharacterRule(digitChars);
+ digitRule.setNumberOfCharacters(2);
+ CharacterData specialChars = new CharacterData() {
+ public String getErrorCode() {
+ return ERROR_CODE;
+ }
+
+ public String getCharacters() {
+ return ALLOWED_SPL_CHARACTERS;
+ }
+ };
+ CharacterRule splCharRule = new CharacterRule(specialChars);
+ splCharRule.setNumberOfCharacters(2);
+ String password = gen.generatePassword(10, splCharRule, lowerCaseRule, upperCaseRule, digitRule);
+ int specialCharCount = 0;
+ for (char c : password.toCharArray()) {
+ if (c >= 33 || c <= 47) {
+ specialCharCount++;
+ }
+ }
+ assertTrue(specialCharCount > 2);
+ }
+
+ /**
+ *
+ * Password Generated using RandomStringGenerator conforming to the password requirements.
+ */
+ @Test
+ public void whenPasswordGeneratedUsingCommonsText_thenSuccessful() {
+ String pwString = generateRandomSpecialCharacters(2).concat(generateRandomNumbers(2))
+ .concat(generateRandomAlphabet(2, true))
+ .concat(generateRandomAlphabet(2, false))
+ .concat(generateRandomCharacters(2));
+ List 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();
+ int specialCharCount = 0;
+ for (char c : password.toCharArray()) {
+ if (c >= 33 || c <= 47) {
+ specialCharCount++;
+ }
+ }
+ assertTrue(specialCharCount > 2);
+ }
+
+ @Test
+ public void whenPasswordGeneratedUsingCommonsLang3_thenSuccessful() {
+ String upperCaseLetters = RandomStringUtils.random(2, 65, 90, true, true);
+ String lowerCaseLetters = RandomStringUtils.random(2, 97, 122, true, true);
+ String numbers = RandomStringUtils.randomNumeric(2);
+ String specialChar = RandomStringUtils.random(2, 33, 47, false, false);
+ String totalChars = RandomStringUtils.randomAlphanumeric(2);
+ String combinedChars = upperCaseLetters.concat(lowerCaseLetters)
+ .concat(numbers)
+ .concat(specialChar)
+ .concat(totalChars);
+ List 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();
+ int specialCharCount = 0;
+ for (char c : password.toCharArray()) {
+ if (c >= 33 || c <= 47) {
+ specialCharCount++;
+ }
+ }
+ assertTrue(specialCharCount > 2);
+ }
+
+ @Test
+ public void whenPasswordGeneratedUsingSecureRandom_thenSuccessful() {
+ Stream pwdStream = Stream.concat(getRandomNumbers(2), Stream.concat(getRandomSpecialChars(2), Stream.concat(getRandomAlphabets(2, true), getRandomAlphabets(4, false))));
+ List charList = pwdStream.collect(Collectors.toList());
+ Collections.shuffle(charList);
+ String password = charList.stream()
+ .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
+ .toString();
+ int specialCharCount = 0;
+ for (char c : password.toCharArray()) {
+ if (c >= 33 || c <= 47) {
+ specialCharCount++;
+ }
+ }
+ assertTrue(specialCharCount > 2);
+ }
+
+ public String generateRandomSpecialCharacters(int length) {
+ RandomStringGenerator pwdGenerator = new RandomStringGenerator.Builder().withinRange(33, 45)
+ .build();
+ return pwdGenerator.generate(length);
+ }
+
+ public String generateRandomNumbers(int length) {
+ RandomStringGenerator pwdGenerator = new RandomStringGenerator.Builder().withinRange(48, 57)
+ .build();
+ return pwdGenerator.generate(length);
+ }
+
+ public String generateRandomCharacters(int length) {
+ RandomStringGenerator pwdGenerator = new RandomStringGenerator.Builder().withinRange(48, 57)
+ .build();
+ return pwdGenerator.generate(length);
+ }
+
+ public String generateRandomAlphabet(int length, boolean lowerCase) {
+ int low;
+ int hi;
+ if (lowerCase) {
+ low = 97;
+ hi = 122;
+ } else {
+ low = 65;
+ hi = 90;
+ }
+ RandomStringGenerator pwdGenerator = new RandomStringGenerator.Builder().withinRange(low, hi)
+ .build();
+ return pwdGenerator.generate(length);
+ }
+
+ public Stream getRandomAlphabets(int count, boolean upperCase) {
+ IntStream characters = null;
+ if (upperCase) {
+ characters = random.ints(count, 65, 90);
+ } else {
+ characters = random.ints(count, 97, 122);
+ }
+ return characters.mapToObj(data -> (char) data);
+ }
+
+ public Stream getRandomNumbers(int count) {
+ IntStream numbers = random.ints(count, 48, 57);
+ return numbers.mapToObj(data -> (char) data);
+ }
+
+ public Stream getRandomSpecialChars(int count) {
+ IntStream specialChars = random.ints(count, 33, 45);
+ return specialChars.mapToObj(data -> (char) data);
+ }
+
+}