【问题标题】:Generate Random String Containing Alpha-Numeric and Special Chars?生成包含字母数字和特殊字符的随机字符串?
【发布时间】:2015-11-09 10:13:11
【问题描述】:

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

  1. 至少 1 个大写字母
  2. 至少 1 个小写字母
  3. 0-9 中至少 1 位数字
  4. 字符 $&@ 中的至少一个特殊字符?~!%#

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

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

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

到目前为止,我已经尝试了以下方法:

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

我知道我可以修改字符串 AB 以包含特殊字符,但无法保证字符串将包含至少 1 个大写字母、1 个小写字母、1 个数字和 1 个特殊字符。

我正在使用 Java。

【问题讨论】:

  • 欢迎来到 Stack Overflow。如果您发布您尝试过的示例并直接提出问题,而不是“什么是最好的方法?”等过于宽泛的问题,您会更快地找到帮助和答案。
  • 研究 Apache 代码,看看如何修改它“以包含特殊字符”。
  • @andrewdleach 发布了一些示例..
  • 或者你可以使用correct horse battery staple。 ;)
  • 我还在等..谢谢

标签: java string random passwords


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

    现在打乱你的字符数组来打乱前四个字符的顺序。

    将洗牌后的数组转换为字符串。

    【讨论】:

      【解决方案3】:

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

      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, "");
          }
      
      }
      

      【讨论】:

        猜你喜欢
        • 2014-07-05
        • 1970-01-01
        • 1970-01-01
        • 2010-09-08
        • 1970-01-01
        • 2013-01-16
        • 2021-04-05
        • 2011-08-18
        • 1970-01-01
        相关资源
        最近更新 更多