2

我想每次都生成一个唯一的密码。我正在使用此代码生成密码。

import java.util.Random;
public class PasswordGenerator
{
    public static String generatePassword()
    {
        Random r[] = new Random[8];
        r[0] = new Random(1234567);
        r[1] = new Random(7654321);
        r[2] = new Random(-1234567);
        r[3] = new Random(-7654321);
        r[4] = new Random(5463721);
        r[5] = new Random(2743615);
        r[6] = new Random(-9753214);
        r[7] = new Random(-3125769);
        Random x = new Random(2325671);
        StringBuilder password = new StringBuilder();
        int length = x.nextInt(5)+9;
        password.setLength(length);
        for(int i=0;i<length;i++)
        {
            x.setSeed(r[i%8].nextInt(500)*r[4].nextInt(900));
            password.setCharAt(i,(char)(r[x.nextInt(256)%8].nextInt(95)+32));
        }
        return password.toString();
    }
}

调用的代码generatePassword()如果它很重要

public void actionPerformed(ActionEvent event)
    {
        if(event.getSource() == generate)
        {
            String userName = username.getText();
            if(userName.isEmpty() || username == null)
            {
                JOptionPane.showMessageDialog(null,"username not entered\nFirst enter your username","ERROR",JOptionPane.ERROR_MESSAGE);
                username.requestFocus();
                username.selectAll();
                return;
            }
            else if(userName.length() <=5)
            {
                JOptionPane.showMessageDialog(null,"Bad Username.\nUsername should be atleast six characters long.","ERROR",JOptionPane.ERROR_MESSAGE);
                username.requestFocus();
                username.selectAll();
                return;
            }
            else
            {
                String passwd = PasswordGenerator.generatePassword();
                password.setText(passwd);
                return;
            }
        }
        else if(event.getSource() == submit)
        {
            String passwordField = password.textField();
            if(passwordField.isEmpty() || passwordField == null)
            {
                JOptionPane.showMessageDialog(null,"Please Generate your password first by clicking on the \"Generate\" button.",JOptionPane.ERROR_MESSAGE);
                generate.requestFocus();
                return;
            }
            else
            {
                //do something...
            }
        }
    }

每次它生成相同的密码,即使我重新编译它。我应该实际修改什么以每次生成唯一密码?

最后工作代码...

import java.util.Random;
public class PasswordGenerator
{
    public static String generatePassword()
    {
        Random r[] = new Random[8];
        for(int i=0;i<8;i++)
            r[i] = new Random();
        Random x = new Random();
        StringBuilder password = new StringBuilder();
        int length = x.nextInt(5)+9;
        password.setLength(length);
        for(int i=0;i<length;i++)
        {
            x.setSeed(r[i%8].nextInt(500)*r[4].nextInt(900));
            password.setCharAt(i,(char)(r[x.nextInt(256)%8].nextInt(95)+32));
        }
        return password.toString();
    }
}

特别感谢@reimeus 和@Jon Skeet

4

4 回答 4

9

每次即使我重新编译它,它也会生成相同的密码。我实际上应该修改什么以每次生成一个唯一的密码?

您正在为 Random 的 9 个实例中的每一个显式提供相同的种子:

Random r[] = new Random[8];
r[0] = new Random(1234567);
r[1] = new Random(7654321);
r[2] = new Random(-1234567);
r[3] = new Random(-7654321);
r[4] = new Random(5463721);
r[5] = new Random(2743615);
r[6] = new Random(-9753214);
r[7] = new Random(-3125769);
Random x = new Random(2325671);

不清楚为什么你甚至多个实例Random,但你不应该指定相同的种子——这将保证你每次都得到相同的结果。只需使用Random不带种子的构造函数,它将根据当前时间选择种子(在现代版本中使用一些 jiggery-pokery 以避免在快速连续多次调用构造函数时使用相同的种子。)

看起来你正在做各种“聪明”的事情来试图让数据更加随机 - 根据调用next不同实例的结果设置一个种子,等等。你让代码更难理解,但不再随机。您仍在使用具有确定性 RNG 的预定种子。那里没有变化的来源。

此外,对于敏感信息,您应该使用SecureRandom而不是Random.

于 2013-07-02T12:57:56.067 回答
2

这是因为您使用固定种子值实例化了 Random 实例:

r[0] = 新随机(1234567);...

来自RandomJavaDoc

如果使用相同的种子创建 Random 的两个实例,并且为每个实例进行相同的方法调用序列,它们将生成并返回相同的数字序列。

于 2013-07-02T12:59:07.360 回答
2

I would suggest that you use the no argument random constructor to declare your Random objects because the one that takes arguments, sets the seed which in turn makes the random object an atomic. I have written an example for you below and I made the result to return exactly 6 characters for your password by setting the password length to six.

import java.util.Random;
public class PasswordGenerator
{
    public static String generatePassword()
{
    Random r[] = new Random[8];
    r[0] = new Random();
    r[1] = new Random();
    r[2] = new Random();
    r[3] = new Random();
    r[4] = new Random();
    r[5] = new Random();
    r[6] = new Random();
    r[7] = new Random();
    Random x = new Random();
    StringBuilder password = new StringBuilder();
    int length = 6;
    password.setLength(length);
    for(int i=0;i<length;i++)
    {
        x.setSeed(r[i%8].nextInt(500)*r[4].nextInt(900));
        password.setCharAt(i,(char)(r[x.nextInt(256)%8].nextInt(95)+32));
    }
    return password.toString();
}

public static void main(String []args){

    System.out.println(PasswordGenerator.generatePassword());
}
}
于 2013-07-02T14:07:08.593 回答
1

关于什么:

r[0] = new Random(System.nanoTime());

The time value might give you a good seed (=parameter for Random).

于 2013-07-02T13:06:10.430 回答