生成包含字母数字和特殊字符的随机字符串?

时间:2015-08-16 19:37:10

标签: java string random passwords

我有兴趣使用以下属性生成(安全)随机字符串:

  1. Atleast 1大写字母
  2. Atleast 1小写字母
  3. 0-9
  4. 的至少1位数字
  5. 来自chars $& @?<>〜!%#
  6. 的一个特殊字符

    字符串的长度应为12-13位/字符长。

    我知道Apache公共中有一个类可以帮助生成随机字符串,但是没有选项可以包含特殊字符。

    我也知道其他一些类似的问题,但是没有一个能完全满足这些要求。

    到目前为止,我已尝试过以下内容:

    import java.security.SecureRandom;
    
    public final class SessionIdentifierGenerator {
      private SecureRandom random = new SecureRandom();
    
      public String nextSessionId() {
        return 
    
        new BigInteger(130, random).toString(32);
          }
        }
    

    但它不包含4个点中的每个点的字符集。

    我也尝试过:

    static final String AB = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    static Random rnd = new Random();
    
    String randomString( int len ) 
    {
       StringBuilder sb = new StringBuilder( len );
       for(int i = 0; i < len; i++) 
          sb.append(AB.charAt( rnd.nextInt(AB.length())));
       return sb.toString();
    }
    

    我知道我可以修改String AB以包含特殊字符但是保证字符串无法包含Atleast 1 upper,1 lower,1 digit和1个特殊字符。

    我正在使用Java。

3 个答案:

答案 0 :(得分:4)

您的最简单方法是生成包含任何允许符号的随机密码,然后测试是否符合条件:

private static final String symbols = 
     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789$&@?<>~!%#";

public static String genPassword(Random r) {
    while(true) {
        char[] password = new char[r.nextBoolean()?12:13];
        boolean hasUpper = false, hasLower = false, hasDigit = false, hasSpecial = false;
        for(int i=0; i<password.length; i++) {
            char ch = symbols.charAt(r.nextInt(symbols.length()));
            if(Character.isUpperCase(ch))
                hasUpper = true;
            else if(Character.isLowerCase(ch))
                hasLower = true;
            else if(Character.isDigit(ch))
                hasDigit = true;
            else
                hasSpecial = true;
            password[i] = ch;
        }
        if(hasUpper && hasLower && hasDigit && hasSpecial) {
            return new String(password);
        }
    }
}

根据我的测试,所需迭代次数很少超过5次,在超过一半的测试中,第一次生成的密码符合标准。虽然不要强迫用户记住这些密码!这是他们的样子:

c3h$oyuKcZZl
Si4e8F4sWjy#i
V$9WwW7zJ8ba
~9htwMwcFc!s
wBm94~AH%z%MU
p4TE36S&Y>J14
R9Bsqq@23eYk
PTfcvR5u?piZQ
CE8ot>a74PmZP
4zAco~P6Xuf3E
aiv?VDN4j9pE

答案 1 :(得分:0)

设置数组/列表/任何字符。选择一个随机的小写字母并将其放入您的数组中。选择一个随机的大写字母并将其放入您的数组中。选择一个随机数字并将其放入数组中。选择一个随机的特殊字符并将其放入数组中。您的阵列中有四个字符,部分符合您的要求。

现在从字符串中随机选择多个字符:&#34; A-Za-z0-9 $&amp; @?&lt;&gt;〜!%#&#34;将每个选定的字符添加到字符数组中。

现在随机播放你的角色数组以搞乱前四个字符的顺序。

将混洗数组转换为字符串。

答案 2 :(得分:0)

以下内容适合我。请注意,如果您不想使用Random,则可以传入特定的RandomUtils实现。

public class RandomUtil {

    public static final String ALPHABETIC_UPPERCASE_SYMBOLS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    public static final String ALPHABETIC_LOWERCASE_SYMBOLS = "abcdefghijklmnopqrstuvwxyz";
    public static final String NUMERIC_SYMBOLS = "0123456789";
    public static final String SPECIAL_SYMBOLS = "$&@?<>~!%#";

    public static final String ALPHANUMERIC_AND_SPECIAL_SYMBOLS =
            ALPHABETIC_UPPERCASE_SYMBOLS + 
            ALPHABETIC_LOWERCASE_SYMBOLS + 
            NUMERIC_SYMBOLS + 
            SPECIAL_SYMBOLS;


    public static String generateRandomAlphanumericAndSpecialCharactersKey(int length) {
        List<Character> chars = new ArrayList<>(length);
        boolean hasUpper = false;
        boolean hasLower = false;
        boolean hasNumber = false;
        boolean hasSpecial = false;
        for (int i = 0; i < length; i++) {
            // Make sure we have at least one upper, lower, number and special character.
            // Then, fill randomly from set containing all characters.
            if (!hasUpper) {
                chars.add(ALPHABETIC_UPPERCASE_SYMBOLS.charAt(RandomUtils.nextInt(0, ALPHABETIC_UPPERCASE_SYMBOLS.length())));
                hasUpper = true;
            } else if (!hasLower) {
                chars.add(ALPHABETIC_LOWERCASE_SYMBOLS.charAt(RandomUtils.nextInt(0, ALPHABETIC_LOWERCASE_SYMBOLS.length())));
                hasLower = true;
            } else if (!hasNumber) {
                chars.add(NUMERIC_SYMBOLS.charAt(RandomUtils.nextInt(0, NUMERIC_SYMBOLS.length())));
                hasNumber = true;
            } else if (!hasSpecial) {
                chars.add(SPECIAL_SYMBOLS.charAt(RandomUtils.nextInt(0, SPECIAL_SYMBOLS.length())));
                hasSpecial = true;
            } else {
                chars.add(ALPHANUMERIC_AND_SPECIAL_SYMBOLS.charAt(RandomUtils.nextInt(0, ALPHANUMERIC_AND_SPECIAL_SYMBOLS.length())));
            }
        }

        // Shuffle characters to mix up the first 4 characters
        Collections.shuffle(chars);

        return StringUtils.join(chars, "");
    }

}