SpringBoot实现密码安全存储的五种方式小结

 更新时间:2025年03月31日 09:34:30   作者:风象南  
项目开发中,密码安全存储是非常关键的一环,作为开发者,我们需要确保用户的密码在存储时被安全地加密,避免因数据泄露而造成严重后果,所以本文给大家介绍了SpringBoot实现密码安全存储的5种方式,需要的朋友可以参考下

为什么不能明文存储密码?

首先,我们需要明确一点:密码永远不能以明文形式存储在数据库中

原因如下:

  • 数据泄露风险:如果数据库被攻击,所有用户的密码将直接暴露。
  • 用户隐私保护:许多用户可能在多个平台使用相同的密码,明文存储会增加其他账户被攻破的风险。
  • 法律与合规要求:许多安全标准(如 GDPR、OWASP 等)都明确禁止明文存储密码。

因此,密码在存储前必须进行加密或哈希处理,在 Spring Boot 中,以下是几种常见的密码安全存储方式。

1. 使用 BCrypt 进行哈希

什么是 BCrypt?

BCrypt 是一种基于 Blowfish 加密算法的哈希函数,专为密码存储设计,具有以下特点:

  • 内置加盐机制,避免彩虹表攻击。
  • 支持设置计算复杂度,可增强哈希强度。
  • 哈希结果固定为 60 个字符,方便存储。

如何使用

  • 引入依赖:如果未使用 Spring Security,需要单独引入 spring-security-crypto
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-crypto</artifactId>
</dependency>
  • 密码加密与验证:使用 BCryptPasswordEncoder 对密码进行加密与验证:
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

public class PasswordUtils {
    private static final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();

    // 加密密码
    public static String encode(String rawPassword) {
        return encoder.encode(rawPassword);
    }

    // 验证密码
    public static boolean matches(String rawPassword, String encodedPassword) {
        return encoder.matches(rawPassword, encodedPassword);
    }
}
  • 使用示例
public static void main(String[] args) {
    String rawPassword = "mypassword";
    String encodedPassword = PasswordUtils.encode(rawPassword);

    System.out.println("加密后的密码:" + encodedPassword);

    boolean isMatch = PasswordUtils.matches(rawPassword, encodedPassword);
    System.out.println("密码匹配结果:" + isMatch);
}

优缺点

  • 优点

    • 安全性高,内置加盐机制。
    • 使用简单,Spring Security 原生支持。
  • 缺点

    • 相较于其他哈希算法,性能略低。

2. 使用 PBKDF2 进行哈希

什么是 PBKDF2?

PBKDF2(Password-Based Key Derivation Function 2)是一种基于密码的密钥派生函数,支持多次迭代计算,进一步增强安全性。

如何使用

  • 引入依赖:如果未使用 Spring Security,需要单独引入 spring-security-crypto
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-crypto</artifactId>
</dependency>
  • 实现密码加密与验证
import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder;

public class PasswordUtils {
    private static final Pbkdf2PasswordEncoder encoder = new Pbkdf2PasswordEncoder();

    // 加密密码
    public static String encode(String rawPassword) {
        return encoder.encode(rawPassword);
    }

    // 验证密码
    public static boolean matches(String rawPassword, String encodedPassword) {
        return encoder.matches(rawPassword, encodedPassword);
    }
}
  • 使用示例
public static void main(String[] args) {
    String rawPassword = "mypassword";
    String encodedPassword = PasswordUtils.encode(rawPassword);

    System.out.println("加密后的密码:" + encodedPassword);

    boolean isMatch = PasswordUtils.matches(rawPassword, encodedPassword);
    System.out.println("密码匹配结果:" + isMatch);
}

优缺点

  • 优点

    • 安全性高,可调节迭代次数。
    • 广泛支持,兼容性好。
  • 缺点

    • 相较 BCrypt,使用稍显复杂。

3. 使用 Argon2 进行哈希

什么是 Argon2?

Argon2 是一种密码哈希算法,2015 年获得密码哈希竞赛(Password Hashing Competition)冠军。它目前被认为是最安全的密码哈希算法之一。

如何使用

  • 引入依赖:如果未使用 Spring Security,需要引入 spring-security-crypto
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-crypto</artifactId>
</dependency>
  • 实现密码加密与验证
import org.springframework.security.crypto.argon2.Argon2PasswordEncoder;

public class PasswordUtils {
    private static final Argon2PasswordEncoder encoder = new Argon2PasswordEncoder();

    // 加密密码
    public static String encode(String rawPassword) {
        return encoder.encode(rawPassword);
    }

    // 验证密码
    public static boolean matches(String rawPassword, String encodedPassword) {
        return encoder.matches(rawPassword, encodedPassword);
    }
}
  • 使用示例
public static void main(String[] args) {
    String rawPassword = "mypassword";
    String encodedPassword = PasswordUtils.encode(rawPassword);

    System.out.println("加密后的密码:" + encodedPassword);

    boolean isMatch = PasswordUtils.matches(rawPassword, encodedPassword);
    System.out.println("密码匹配结果:" + isMatch);
}

优缺点

  • 优点
    • 安全性极高,专为现代硬件设计。
    • 防御 GPU 加速的暴力 破解。
  • 缺点
    • 算法较新,部分老旧系统可能不支持。

4. SCrypt

什么是 SCrypt?

SCrypt 是一种基于密码的密钥派生函数,尤其适用于限制硬件加速的攻击(如 GPU 加速的暴力 破解)。它通过增加内存使用量,显著提高了破解成本。

SCrypt 的特点

  • 高安全性:通过增加内存占用,防止大规模硬件加速的攻击。
  • 参数可调:可以调整计算强度和内存使用量,适应不同的性能需求。

如何使用

Spring Security 提供了对 SCrypt 的支持,可以直接使用 SCryptPasswordEncoder

  • 实现代码
import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;

public class PasswordUtils {
    private static final SCryptPasswordEncoder encoder = new SCryptPasswordEncoder();

    // 加密密码
    public static String encode(String rawPassword) {
        return encoder.encode(rawPassword);
    }

    // 验证密码
    public static boolean matches(String rawPassword, String encodedPassword) {
        return encoder.matches(rawPassword, encodedPassword);
    }
}
  • 使用示例
public static void main(String[] args) {
    String rawPassword = "mypassword";
    String encodedPassword = PasswordUtils.encode(rawPassword);

    System.out.println("加密后的密码:" + encodedPassword);

    boolean isMatch = PasswordUtils.matches(rawPassword, encodedPassword);
    System.out.println("密码匹配结果:" + isMatch);
}

优缺点

  • 优点

    • 抗 GPU 攻击能力强。
    • 参数可调,灵活性高。
  • 缺点

    • 性能较低,适合对安全性要求较高的场景。

5. SHA-256 + Salt

什么是 SHA-256?

SHA-256 是一种广泛使用的哈希算法,属于 SHA-2 家族。它生成固定长度的 256 位哈希值,计算速度快且实现简单。单独使用 SHA-256 不安全,因为它无法抵抗彩虹表攻击。因此,通常需要搭配 Salt(随机盐值) 使用。

实现原理

  • 加盐:为每个密码生成一个随机盐值,增加哈希结果的随机性。
  • 迭代:多次循环计算,增加破解难度。

如何使用

需要手动实现加盐和迭代逻辑,可以使用 Java 的 MessageDigest 类。

  • 实现代码
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Base64;

public class PasswordUtils {

    // 生成随机盐值
    public static String generateSalt() {
        byte[] salt = new byte[16];
        new SecureRandom().nextBytes(salt);
        return Base64.getEncoder().encodeToString(salt);
    }

    // 使用 SHA-256 进行加密
    public static String hashPassword(String password, String salt) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            String saltedPassword = salt + password;
            byte[] hash = digest.digest(saltedPassword.getBytes());
            for (int i = 0; i < 1000; i++) {  // 多次迭代
                hash = digest.digest(hash);
            }
            return Base64.getEncoder().encodeToString(hash);
        } catch (Exception e) {
            throw new RuntimeException("加密失败", e);
        }
    }

    // 验证密码
    public static boolean matches(String rawPassword, String salt, String hashedPassword) {
        return hashPassword(rawPassword, salt).equals(hashedPassword);
    }
}
  • 使用示例
public static void main(String[] args) {
    String rawPassword = "mypassword";
    String salt = PasswordUtils.generateSalt();
    String hashedPassword = PasswordUtils.hashPassword(rawPassword, salt);

    System.out.println("随机盐值:" + salt);
    System.out.println("加密后的密码:" + hashedPassword);

    boolean isMatch = PasswordUtils.matches(rawPassword, salt, hashedPassword);
    System.out.println("密码匹配结果:" + isMatch);
}

优缺点

  • 优点

    • 实现简单,速度快。
    • 可用于与旧系统兼容的场景。
  • 缺点

    • 安全性相对较低,需谨慎处理盐值。

总结

加密方式安全性性能适用场景
BCrypt中等通用场景,兼容性好
PBKDF2中等高强度密码存储
Argon2极高较低对安全性要求极高的场景
SCrypt极高较低防硬件加速攻击的场景
SHA-256 + Salt中等安全性不敏感的项目,如内部项目

推荐选择

  • 通用场景:推荐使用 BCrypt,它在性能和安全性之间达到了良好平衡。
  • 高安全性需求:建议使用 Argon2SCrypt
  • 安全性不敏感的系统:可以考虑 SHA-256 + Salt

以上就是SpringBoot实现密码安全存储的五种方式小结的详细内容,更多关于SpringBoot密码存储的资料请关注脚本之家其它相关文章!

相关文章

  • SpringBoot + proguard+maven多模块实现代码混淆的方法

    SpringBoot + proguard+maven多模块实现代码混淆的方法

    这篇文章主要介绍了SpringBoot + proguard+maven多模块实现代码混淆的方法,多模块跟单模块一样,在需要混淆模块的pom文件中加入proguard依赖及配置,本文给大家讲解的非常详细,感兴趣的朋友一起看看吧
    2024-02-02
  • Java Optional<Foo>转换成List<Bar>的实例方法

    Java Optional<Foo>转换成List<Bar>的实例方法

    在本篇内容里小编给大家整理的是一篇关于Java Optional<Foo>转换成List<Bar>的实例方法,有需要的朋友们可以跟着学习下。
    2021-06-06
  • 浅谈Spring Boot日志框架实践

    浅谈Spring Boot日志框架实践

    这篇文章主要介绍了浅谈Spring Boot日志框架实践,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-03-03
  • 基于雪花算法实现增强版ID生成器详解

    基于雪花算法实现增强版ID生成器详解

    这篇文章主要为大家详细介绍了如何基于雪花算法实现增强版ID生成器,文中的示例代码讲解详细,对我们学习具有一定的借鉴价值,需要的可以了解一下
    2022-10-10
  • java连接SQL Server数据库的超详细教程

    java连接SQL Server数据库的超详细教程

    最近在java连接SQL数据库时会出现一些问题,所以这篇文章主要给大家介绍了关于java连接SQL Server数据库的超详细教程,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2022-06-06
  • 关于IDEA报错Error:java 不支持发行版本17的原因及解决方案

    关于IDEA报错Error:java 不支持发行版本17的原因及解决方案

    在rebuild或运行项目时提示“Error:java: 错误: 不支持发行版本 17”,本文将给大家介绍了IDEA提示“Error:java: 错误: 不支持发行版本17”的原因及解决方案,需要的朋友可以参考下
    2023-09-09
  • 解决eclipse中console控制选项不见了的方法

    解决eclipse中console控制选项不见了的方法

    eclipse是一款用于编译java语言的程序,利用这款软件我们可以制作很多有趣的小程序,也可以制作一些大型的软件项目,有的用户在使用eclipse的时候会遇到console消失的情况,所以本文给大家介绍了解决eclipse中console控制选项不见了的方法,需要的朋友可以参考下
    2024-03-03
  • JavaWeb详细讲述Cookie和Session的概念

    JavaWeb详细讲述Cookie和Session的概念

    web开发阶段我们主要是浏览器和服务器之间来进行交互。浏览器和服务器之间的交互就像人和人之间进行交流一样,但是对于机器来说,在一次请求之间只是会携带着本次请求的数据的,但是可能多次请求之间是会有联系的,所以提供了会话机制
    2022-06-06
  • Java多线程实现聊天客户端和服务器

    Java多线程实现聊天客户端和服务器

    这篇文章主要为大家详细介绍了Java多线程聊天客户端和服务器实现代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • mybatis某些字段无法映射成功的解决

    mybatis某些字段无法映射成功的解决

    这篇文章主要介绍了mybatis某些字段无法映射成功的解决方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11

最新评论