十个方法破解Java生成随机密码的小窍门

简介: 十个方法破解Java生成随机密码的小窍门

1. 使用Java标准库中的Random

import java.util.Random;

public class RandomPasswordGenerator {
    private static final String CHAR_LIST = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
    private static final int LENGTH = 10;

    public static void main(String[] args) {
        System.out.println(generateRandomPassword());
    }

    public static String generateRandomPassword() {

        Random random = new Random();
        StringBuilder password = new StringBuilder();

        for (int i = 0; i < LENGTH; i++) {
            int index = random.nextInt(CHAR_LIST.length());
            password.append(CHAR_LIST.charAt(index));
        }

        return password.toString();
    }
}

在这个例子中,我们定义了一个包含所有可能字符的字符串CHAR_LIST,然后随机选择其中的字符来生成密码。

2. 使用Java 8中的SecureRandomBase64

如果你需要生成更安全的随机密码,可以使用SecureRandom类,它提供了更好的随机性。同时,我们可以使用Base64编码来确保密码包含特殊字符并且易于打印。

import java.security.SecureRandom;
import java.util.Base64;

public class SecureRandomPasswordGenerator {
    private static final int LENGTH = 20; // Base64编码后的长度

    public static void main(String[] args) {
        System.out.println(generateSecureRandomPassword());
    }

    public static String generateSecureRandomPassword() {
        SecureRandom random = new SecureRandom();
        byte[] passwordBytes = new byte[LENGTH];
        random.nextBytes(passwordBytes);

        // Base64编码,然后去掉末尾的'='字符,因为它可能会引起一些问题
        String password = Base64.getEncoder().encodeToString(passwordBytes).replaceAll("=", "");

        // Base64编码后的字符串可能会比原始字节数组长,所以我们需要截取所需长度的部分
        return password.substring(0, Math.min(password.length(), LENGTH));
    }
}

由于Base64编码的特性,生成的密码可能包含/+=等特殊字符。

3. 使用ThreadLocalRandom

ThreadLocalRandom类是Java 7引入的,它提供了更好的线程安全性以及在某些情况下的更高性能。

import java.util.concurrent.ThreadLocalRandom;

public class PasswordGenerator {
    private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~`!@#$%^&*()_-+={[}]|:;\"'<,>.?/";
    private static final int PASSWORD_LENGTH = 12;

    public static String generatePassword() {
        char[] password = new char[PASSWORD_LENGTH];
        for (int i = 0; i < PASSWORD_LENGTH; i++) {
            int index = ThreadLocalRandom.current().nextInt(CHARACTERS.length());
            password[i] = CHARACTERS.charAt(index);
        }
        return new String(password);
    }

    public static void main(String[] args) {
        System.out.println(generatePassword());
    }
}

4. 使用java.util.Collections.shuffle()

你可以创建一个字符列表,然后使用Collections.shuffle()方法来随机打乱它,最后从打乱的列表中选取字符来构建密码。

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class PasswordGenerator {
    private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~`!@#$%^&*()_-+={[}]|:;\"'<,>.?/";
    private static final int PASSWORD_LENGTH = 12;

    public static String generatePassword() {
        List<Character> charactersList = new ArrayList<>();
        for (char c : CHARACTERS.toCharArray()) {
            charactersList.add(c);
        }
        Collections.shuffle(charactersList);

        StringBuilder password = new StringBuilder();
        for (int i = 0; i < PASSWORD_LENGTH; i++) {
            password.append(charactersList.get(i));
        }
        return password.toString();
    }

    public static void main(String[] args) {
        System.out.println(generatePassword());
    }
}

5. 使用第三方库

你还可以使用像Apache Commons Lang或Google Guava这样的第三方库来生成随机密码。这些库通常提供了现成的工具类和方法来简化随机字符串的生成。

例如,在Apache Commons Lang中,你可以使用RandomStringUtils类:

import org.apache.commons.lang3.RandomStringUtils;

public class PasswordGenerator {
    private static final int PASSWORD_LENGTH = 12;

    public static String generatePassword() {
        return RandomStringUtils.randomAlphanumeric(PASSWORD_LENGTH) +
                RandomStringUtils.randomAscii(2).replaceAll("\\W", ""); // To include special characters
    }

    public static void main(String[] args) {
        System.out.println(generatePassword());
    }
}

注意,RandomStringUtils.randomAscii(2).replaceAll("\\W", "")这种方式生成特殊字符并不是特别高效,因为它可能会生成不需要的字符然后删除它们。更好的做法是直接定义一个包含所需特殊字符的字符串,并从中随机选择。

6. 结合多种字符类型

如果你需要确保密码包含大写字母、小写字母、数字和特殊字符,你可以分别从这些类型的字符集中随机选择字符,然后组合它们来生成密码。

import java.util.Random;

public class ComplexPasswordGenerator {
    private static final String UPPER_ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final String LOWER_ALPHA = "abcdefghijklmnopqrstuvwxyz";
    private static final String NUMBERS = "0123456789";
    private static final String SPECIAL_CHARS = "~`!@#$%^&*()_-+={[}]|:;\"'<,>.?/";
    private static final int PASSWORD_LENGTH = 12;

    public static String generatePassword() {
        Random rand = new Random();
        StringBuilder password = new StringBuilder();

        // Ensure at least one character from each group
        password.append(UPPER_ALPHA.charAt(rand.nextInt(UPPER_ALPHA.length())));
        password.append(LOWER_ALPHA.charAt(rand.nextInt(LOWER_ALPHA.length())));
        password.append(NUMBERS.charAt(rand.nextInt(NUMBERS.length())));
        password.append(SPECIAL_CHARS.charAt(rand.nextInt(SPECIAL_CHARS.length())));

        // Fill the rest with characters from all groups
        for (int i = 4; i < PASSWORD_LENGTH; i++) {
            String characterSet = getRandomCharacterSet(rand);
            password.append(characterSet.charAt(rand.nextInt(characterSet.length())));
        }

        return password.toString();
    }

    private static String getRandomCharacterSet(Random rand) {
        int randomIndex = rand.nextInt(4);
        switch (randomIndex) {
            case 0:
                return UPPER_ALPHA;
            case 1:
                return LOWER_ALPHA;
            case 2:
                return NUMBERS;
            default:
                return SPECIAL_CHARS;
        }
    }

    public static void main(String[] args) {
        System.out.println(generatePassword());
    }
}

我们首先确保密码至少包含一个大写字母、一个小写字母、一个数字和一个特殊字符,然后随机从所有字符集中选择字符来填充密码的其余部分。

7. 使用Google的Guava库

Guava库提供了很多实用的工具,包括生成随机字符串的功能。

首先,添加Guava库到你的项目中:

<!-- Maven dependency -->  
<dependency>  
    <groupId>com.google.guava</groupId>  
    <artifactId>guava</artifactId>  
    <version>30.1-jre</version> <!-- 请检查最新版本 -->  
</dependency>

然后,使用Guava的CharMatcher和CharSource来生成密码:

import com.google.common.base.CharMatcher;  
import com.google.common.math.IntMath;  
import com.google.common.collect.ImmutableList;  
  
import java.security.SecureRandom;  
import java.util.List;  
import java.util.Random;  
  
public class GuavaPasswordGenerator {  
    private static final int PASSWORD_LENGTH = 12;  
    private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~`!@#$%^&*()_-+={[}]|:;\"'<,>.?/";  
    private static final List<Character> CHARACTER_LIST = ImmutableList.copyOf(CHARACTERS.chars().mapToObj(c -> (char) c).collect(ImmutableList.toImmutableList()));  
  
    public static String generatePassword() {  
        Random random = new SecureRandom();  
        String password = CharMatcher.any().retainFrom(  
                CharSource.fromChars(CHARACTER_LIST)  
                        .sampled(IntMath.checkedMultiply(PASSWORD_LENGTH, 4)) // 多取一些字符以增加随机性  
                        .retainAll(CharMatcher.anyOf(CHARACTERS))  
                        .toString(),  
                PASSWORD_LENGTH);  
        return password;  
    }  
  
    public static void main(String[] args) {  
        System.out.println(generatePassword());  
    }  
}

先从CHARACTERS字符串中创建了一个字符列表,然后使用Guava的CharSource从这个列表中随机采样字符,并使用CharMatcher保留指定数量的字符来生成密码。这里使用SecureRandom来确保随机性。但是,请注意Guava的CharSource.sampled()方法并不是加密安全的,因此在实际应用中可能需要额外的考虑。对于加密安全的密码生成,最好直接使用SecureRandom或类似的加密安全库。


当然,我们可以继续探讨更多关于生成随机密码的Java方法。这里,我将介绍一种使用Java标准库中的Base64编码来生成密码的方法,以及一种自定义字符集和密码长度的方法。

8. 使用Base64编码生成密码

Base64编码可以将任意二进制数据转换为由64个特定字符组成的文本格式。我们可以生成随机的字节数组,然后将其编码为Base64字符串,最后截取所需的长度作为密码。

import java.util.Base64;
import java.security.SecureRandom;
import java.nio.charset.StandardCharsets;

public class Base64PasswordGenerator {
    private static final int BYTE_ARRAY_LENGTH = 9; // Base64编码后会变得更长,所以需要更短的字节数组来达到期望的密码长度
    private static final int PASSWORD_LENGTH = 12; // 最终的密码长度

    public static String generatePassword() {
        SecureRandom random = new SecureRandom();
        byte[] randomBytes = new byte[BYTE_ARRAY_LENGTH];
        random.nextBytes(randomBytes);
        
        // 使用Base64编码,然后截取所需长度的字符串作为密码
        String base64Encoded = Base64.getEncoder().encodeToString(randomBytes);
        return base64Encoded.substring(0, PASSWORD_LENGTH);
    }

    public static void main(String[] args) {
        System.out.println(generatePassword());
    }
}

注意:Base64编码可能会包含+, /, 和=字符,这些字符在某些情况下可能需要被替换或移除,以避免在密码中使用。此外,由于Base64编码的特性,截取的字符串可能不是有效的Base64编码序列。

9. 自下面的方法允许你指定用于生成密码的字符集和密码的长度。

import java.security.SecureRandom;

public class CustomPasswordGenerator {
    private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~`!@#$%^&*()_-+={[}]|:;\"'<,>.?/";
    private static SecureRandom random = new SecureRandom();

    public static String generatePassword(int length) {
        if (length < 1) {
            throw new IllegalArgumentException("Password length must be positive.");
        }
        
        StringBuilder password = new StringBuilder(length);
        for (int i = 0; i < length; i++) {
            int index = random.nextInt(CHARACTERS.length());
            password.append(CHARACTERS.charAt(index));
        }
        return password.toString();
    }

    public static void main(String[] args) {
        int passwordLength = 16; // 自定义密码长度
        System.out.println(generatePassword(passwordLength));
    }
}

定义一个generatePassword方法,它接受一个整数参数length来指定密码的长度。我们使用SecureRandom来随机选择字符集中的字符,直到达到所需的密码长度。

10. 结合固定和随机字符

这种方法是先创建一个固定的模板字符串,然后在模板中的指定位置插入随机字符。

import java.security.SecureRandom;

public class TemplateBasedPasswordGenerator {
    private static final String TEMPLATE = "AbcD-####-!";
    private static final String NUMBERS = "0123456789";

    public static String generatePassword() {
        SecureRandom secureRandom = new SecureRandom();
        StringBuilder password = new StringBuilder(TEMPLATE);

        for (int i = 0; i < password.length(); i++) {
            char c = password.charAt(i);
            if (c == '#') {
                int index = secureRandom.nextInt(NUMBERS.length());
                password.setCharAt(i, NUMBERS.charAt(index));
            }
        }

        return password.toString();
    }

    public static void main(String[] args) {
        System.out.println(generatePassword());
    }
}

模板是"AbcD-####-!"#字符会被随机数字替换。

11. 使用正则表达式

如果你需要密码符合特定的格式,你可以使用正则表达式来验证生成的密码。

import java.security.SecureRandom;
import java.util.regex.Pattern;

public class RegexPasswordGenerator {
    private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~`!@#$%^&*()_-+={[}]|:;\"'<,>.?/";
    private static final int PASSWORD_LENGTH = 12;
    private static final Pattern PASSWORD_PATTERN = Pattern.compile("^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[!@#$%^&*()_\\-+={[}\\]|:;\"'<,>.?/]).{12}$");

    public static String generatePassword() {
        SecureRandom secureRandom = new SecureRandom();
        StringBuilder password = new StringBuilder();
        boolean isValid = false;

        while (!isValid) {
            password.setLength(0);
            for (int i = 0; i < PASSWORD_LENGTH; i++) {
                int index = secureRandom.nextInt(CHARACTERS.length());
                password.append(CHARACTERS.charAt(index));
            }
            isValid = PASSWORD_PATTERN.matcher(password.toString()).matches();
        }

        return password.toString();
    }

    public static void main(String[] args) {
        System.out.println(generatePassword());
    }
}

PASSWORD_PATTERN定义了一个正则表达式,要求密码至少包含一个小写字母、一个大写字母、一个数字和一个特殊字符,并且长度为12。



相关文章
|
13天前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
53 4
|
23天前
|
Java API
Java 对象释放与 finalize 方法
关于 Java 对象释放的疑惑解答,以及 finalize 方法的相关知识。
43 17
|
17天前
|
Java 测试技术 Maven
Java一分钟之-PowerMock:静态方法与私有方法测试
通过本文的详细介绍,您可以使用PowerMock轻松地测试Java代码中的静态方法和私有方法。PowerMock通过扩展Mockito,提供了强大的功能,帮助开发者在复杂的测试场景中保持高效和准确的单元测试。希望本文对您的Java单元测试有所帮助。
32 2
|
1月前
|
算法 Java Linux
java制作海报二:java使用Graphics2D 在图片上合成另一个照片,并将照片切割成头像,头像切割成圆形方法详解
这篇文章介绍了如何使用Java的Graphics2D类在图片上合成另一个照片,并将照片切割成圆形头像的方法。
49 1
java制作海报二:java使用Graphics2D 在图片上合成另一个照片,并将照片切割成头像,头像切割成圆形方法详解
|
25天前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
19 3
|
27天前
|
Java 大数据 API
别死脑筋,赶紧学起来!Java之Steam() API 常用方法使用,让开发简单起来!
分享Java Stream API的常用方法,让开发更简单。涵盖filter、map、sorted等操作,提高代码效率与可读性。关注公众号,了解更多技术内容。
|
25天前
|
Java 开发者
在Java多线程编程中,选择合适的线程创建方法至关重要
【10月更文挑战第20天】在Java多线程编程中,选择合适的线程创建方法至关重要。本文通过案例分析,探讨了继承Thread类和实现Runnable接口两种方法的优缺点及适用场景,帮助开发者做出明智的选择。
16 2
|
25天前
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
16 1
|
25天前
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
28 1
|
25天前
|
Java
在Java多线程编程中,`wait()`和`notify()`方法的相遇如同一场奇妙的邂逅
在Java多线程编程中,`wait()`和`notify()`方法的相遇如同一场奇妙的邂逅。它们用于线程间通信,使线程能够协作完成任务。通过这些方法,生产者和消费者线程可以高效地管理共享资源,确保程序的有序运行。正确使用这些方法需要遵循同步规则,避免虚假唤醒等问题。示例代码展示了如何在生产者-消费者模型中使用`wait()`和`notify()`。
24 1