[英]How to guarantee certain characters in a random password
我使用该功能可以生成长度为11的随机密码,在看到这个帖子:
import java.util.Random;
public class RandomPassword {
public static void main(String[] args){
RandomPassword r = new RandomPassword(11);
System.out.print(r.nextString());
}
private static final char[] symbols;
static {
StringBuilder tmp = new StringBuilder();
for (char ch = '0'; ch <= '9'; ++ch)
tmp.append(ch);
for (char ch = 'a'; ch <= 'z'; ++ch)
tmp.append(ch);
for (char ch = 'A'; ch <= 'Z'; ++ch)
tmp.append(ch);
symbols = tmp.toString().toCharArray();
}
private final Random random = new Random();
private final char[] buf;
public RandomPassword(int length) {
if (length < 1)
throw new IllegalArgumentException("length < 1: " + length);
buf = new char[length];
}
public String nextString() {
for (int idx = 0; idx < buf.length; ++idx)
buf[idx] = symbols[random.nextInt(symbols.length)];
return new String(buf);
}
}
但是,我需要对其进行修改,以便可以保证至少一个大写字母,一个数字和一个小写字母。 现在,该密码可能包含所有大写字母/小写字母/数字,并且我们至少需要其中之一才能被AD接受。 任何帮助表示赞赏,谢谢。
***有人告诉我,最好在nextString()
这样循环遍历:
public String nextString() {
for (int idx = 0; idx < buf.length; ++idx)
if(buf[buf.length%3].equals(num/lower/cap)){
buf[idx] = symbols[random.nextInt(symbols.length)];
}
.
.
.
return new String(buf);
}
你怎么看?
这将防止循环,并且还具有真正随机的好处。
或者,如果可以接受一些熵损失,则可以:
循环遍历数组中的字符以确保每个字符类都包含在其中。 然后,如果失败,只需生成一个新的随机字符串。 这样可以确保所有内容都包含在内并且不会经常失败。
我建议您定期搜索一组预定义的字符/数字(大写/小写)和错误消息
public String getPassword(){
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "SUN");
byte[] salt = new byte[16];
sr.nextBytes(salt);
return wellformedPassword(salt.toString()) ? salt.toString() : secured(salt.toString());
}
public String secured(String pass){
return string1.replaceFirst(Pattern.quote("[a-z]", "Z");
}
public boolean wellformedPassword(String pass){
return checkRegExp(pass, "\\d")
&& checkRegExp(pass, "[A-Z]")
&& checkRegExp(pass, "[a-z]");
}
public boolean checkRegExp(String str, String pattern){
Pattern p = Pattern.compile(pattern);
Matcher n = p.matcher(str);
return n.find();
}
SHA向您保证小写字母和数字,然后您只需将一个或多个(就我而言)向上翻。
这是一种可以改进的虚拟方法。 分享您的代码,这样我以后就无法编辑其他人的答案。
您可以获取该字符并将其转到Z的上方,而不是Z,但是我想您可以开始使用。
此“作弊”(比可能弱),但满足通常的要求(或可以进行修改以满足这些要求):
import java.util.Random;
public class Password {
private static final String UPPER = "ABCDEFGHIJKLMNPQRSTUVWXYZ";
private static final String LOWER = "abcdefghijklmnpqrstuvwxyz";
private static final String NUMBER = "123456789";
private static final String SPECIAL = "!@#$%&*+?";
private Random randGen = new Random();
public static void main(String[] argv) {
Password me = new Password();
for (int i = 0; i <= 10; i++) {
me.printPassword();
}
}
private void printPassword() {
StringBuffer buf = new StringBuffer();
buf.append(LOWER.charAt(Math.abs(randGen.nextInt()) % LOWER.length()));
buf.append(LOWER.charAt(Math.abs(randGen.nextInt()) % LOWER.length()));
buf.append(NUMBER.charAt(Math.abs(randGen.nextInt()) % NUMBER.length()));
for (int i = 0; i <= 4; i++) {
buf.append(LOWER.charAt(Math.abs(randGen.nextInt()) % LOWER.length()));
}
buf.append(UPPER.charAt(Math.abs(randGen.nextInt()) % UPPER.length()));
buf.append(LOWER.charAt(Math.abs(randGen.nextInt()) % LOWER.length()));
System.out.println(buf.toString());
}
}
我有另一种更好的算法,但失败了。
(我喜欢打印出多个“建议”,然后选择似乎最容易记住的建议。)
我真的不知道它有多可靠,但尝试一下
List<Character> listOfUpperCaseLetter = new ArrayList<Character>();
for(int i = 65;i<91;i++){
char ch = (char)i;
listOfUpperCaseLetter.add(ch);
}
List<Character> listOfLowerCaseLetter = new ArrayList<Character>();
for(int i = 97;i<123;i++){
char ch = (char)i;
listOfLowerCaseLetter.add(ch);
}
List<Integer> listOfInt = new ArrayList<Integer>();
for(int i =0;i<10;i++){
listOfInt.add(i);
}
StringBuilder br = new StringBuilder();
Collections.shuffle(listOfLowerCaseLetter);
Collections.shuffle(listOfUpperCaseLetter);
Collections.shuffle(listOfInt);
br.append(listOfUpperCaseLetter.get(0));
br.append(listOfLowerCaseLetter.get(1));
br.append(listOfLowerCaseLetter.get(3));
br.append(listOfInt.get(1));
br.append(listOfInt.get(0));
br.append(listOfLowerCaseLetter.get(2));
br.append(listOfUpperCaseLetter.get(1));
br.append(listOfLowerCaseLetter.get(0));
br.append(listOfUpperCaseLetter.get(2));
br.append(listOfInt.get(2));
System.out.println(br.toString());
我只是添加了一条if/else
语句,说要添加symbols
数组的某些成员(0-10、11-35、36-61)。 这保证了所需要的。 有时,最简单的答案就是最好的答案。 感谢您的想法。
if (idx == 0){
buf[idx] = symbols[random.nextInt(10)];
}else if (idx == 1){
buf[idx] = symbols[10 + random.nextInt(35-10+1)];
}else if(idx == 2){
buf[idx] = symbols[36 + random.nextInt(61-36+1)];
}else{
buf[idx] = symbols[random.nextInt(symbols.length)];
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.