【问题标题】:Why does my Password generation code not work as expected?为什么我的密码生成代码不能按预期工作?
【发布时间】:2013-07-02 12:55:31
【问题描述】:

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

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

【问题讨论】:

    标签: java random password-generator


    【解决方案1】:

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

    明确为您的 9 个 Random 实例中的每一个提供相同的种子:

    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

    【讨论】:

    • 好的,明白了。谢谢你们的帮助,现在可以了。
    • hmmm SecureRandom ...好的,我会记住的,再次感谢
    【解决方案2】:

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

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

    来自Random JavaDoc

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

    【讨论】:

      【解决方案3】:

      我建议您使用无参数随机构造函数来声明您的 Random 对象,因为接受参数的构造函数设置种子,这反过来又使随机对象成为原子对象。我在下面为您编写了一个示例,通过将密码长度设置为 6,我使结果为您的密码准确返回 6 个字符。

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

      【讨论】:

        【解决方案4】:

        怎么样:

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

        时间值可能会给你一个很好的种子(=随机参数)。

        【讨论】:

          猜你喜欢
          • 2017-06-08
          • 1970-01-01
          • 2020-11-10
          • 2021-12-11
          • 1970-01-01
          • 1970-01-01
          • 2021-05-10
          • 2015-06-09
          • 1970-01-01
          相关资源
          最近更新 更多