当前位置: 首页 > news >正文

密码加密算法和JWT无状态认证

加密算法分类

一、单向散列算法(不可逆,推荐用于密码存储)

单向散列算法通过哈希函数将任意长度的密码转换为固定长度的哈希值(密文),且无法从哈希值反推原始密码,是密码存储的首选方案。为增强安全性,通常会结合盐值(Salt) 使用(给每个密码添加随机字符串后再哈希,防止彩虹表攻击)。

1. MD5(Message-Digest Algorithm 5)
  • 特点:生成 128 位(16 字节)哈希值,运算速度快,但安全性极低。
  • 缺陷:已被证明存在严重漏洞,可通过碰撞攻击伪造相同哈希值的不同明文,不适合密码存储。
  • 现状:仅用于非安全场景(如文件校验),严禁用于密码加密。
2. SHA 系列(Secure Hash Algorithm)
  • SHA-1:生成 160 位哈希值,安全性低于 SHA-2,已被破解,不推荐用于密码。
  • SHA-2:包括 SHA-256、SHA-384、SHA-512 等,生成 256/384/512 位哈希值,安全性高,应用广泛。
    • 例:SHA-256 是目前主流选择,抗碰撞能力强,适合结合盐值存储密码。
  • SHA-3:SHA-2 的替代方案,基于全新算法设计,安全性更高,但目前应用较少。
3. BCrypt
  • 特点:专为密码哈希设计,基于 Blowfish 加密算法,自带盐值机制,且可通过 “工作因子” 调整运算复杂度(随硬件升级提高破解难度)。
  • 优势:不可逆、抗暴力破解能力强,是业界推荐的密码加密算法之一(如 Spring Security 默认支持)。

二、可逆加密算法(不推荐直接用于密码存储)

可逆加密算法(对称 / 非对称)可通过密钥解密得到原始密码,若密钥泄露,密码会直接暴露,因此不适合直接存储密码,仅用于临时加密传输场景。

1. 对称加密算法
  • AES(Advanced Encryption Standard):目前最流行的对称加密算法,支持 128/192/256 位密钥,安全性高、速度快。
  • DES/3DES:DES 已被破解,3DES 是 DES 的改进版但效率低,逐渐被 AES 替代。
2. 非对称加密算法
  • RSA:基于大数分解难题,用于密钥交换或数字签名,加密速度慢,不适合大量数据(如密码)加密。

三、密码加密的最佳实践

  1. 优先使用专用哈希算法:选择 BCrypt、Argon2 或 PBKDF2,避免 MD5、SHA-1。
  2. 强制使用盐值:每个密码对应唯一随机盐值,与哈希值一起存储(盐值无需保密)。
  3. 动态调整复杂度:根据硬件性能提高算法的迭代次数或内存消耗(如 BCrypt 的工作因子、Argon2 的内存参数)。
  4. 禁止可逆加密:除非特殊场景(如临时密码传输),否则不使用 AES、RSA 等可逆算法存储密码。

总结:Argon2 和 BCrypt 是当前密码加密的最优选择,兼顾安全性和实用性;SHA-256 结合盐值和高迭代次数可作为次选;MD5、DES 等已彻底淘汰。

BCrypt加密原理

代码实现:

##加密部分
public String encodePassword(String rawPassword) {if (rawPassword == null || rawPassword.isEmpty()) {throw new IllegalArgumentException("密码不能为空");}String encodedPassword = passwordEncoder.encode(rawPassword);log.debug("密码已加密");return encodedPassword;
}
##匹配部分
public boolean matches(String rawPassword, String encodedPassword) {if (rawPassword == null || encodedPassword == null) {return false;}boolean matches = passwordEncoder.matches(rawPassword, encodedPassword);log.debug("密码匹配结果: {}", matches);return matches;
}

1. 核心原理:加密算法的 “验证逻辑”

现代密码加密算法(如 BCrypt、Argon2、PBKDF2 等)的 matches 方法并非简单的 “重新加密原始密码并比较密文”,而是基于算法特性设计的验证逻辑:

  • 加密时,算法会自动生成随机盐值(salt),并将盐值与加密后的哈希值一起存储在 encodedPassword 中(密文通常包含盐值 + 哈希值 + 算法参数,格式如 $2a$10$N9qo8uLOickgx2ZMRZo5MeVQ82iT1M3Q)。
  • 验证时,matches 方法会:
    1. 从 encodedPassword 中解析出盐值、算法参数(如迭代次数、工作因子等)。
    2. 使用相同的盐值和参数,对用户输入的 rawPassword 执行相同的加密流程,生成临时哈希值。
    3. 比较临时哈希值与 encodedPassword 中存储的哈希值是否一致,一致则返回 true

2. 示例流程(以 BCrypt 为例)

假设你的 passwordEncoder 是 BCrypt 加密器:

  • 加密时
    passwordEncoder.encode("123456") 会生成类似 $2a$10$N9qo8uLOickgx2ZMRZo5MeVQ82iT1M3Q 的密文,其中:

    • $2a$ 表示 BCrypt 算法版本。
    • 10$ 表示工作因子(迭代次数)。
    • N9qo8uLOickgx2ZMRZo5Me 是随机盐值。
    • 后续部分是盐值 + 原始密码的哈希结果。
  • 验证时
    passwordEncoder.matches("123456", "$2a$10$N9qo8uLOickgx2ZMRZo5MeVQ82iT1M3Q") 会:

    1. 从密文中解析出盐值 N9qo8uLOickgx2ZMRZo5Me 和工作因子 10
    2. 用同样的盐值和工作因子,对输入的 123456 重新执行 BCrypt 加密。
    3. 比较新生成的哈希值与密文中的哈希部分是否相同,相同则返回 true

3. 为什么不需要手动处理盐值?

现代加密框架(如 Spring Security 的 PasswordEncoder)已封装了盐值的生成、存储和提取逻辑:

  • 盐值无需单独存储,而是嵌入在 encodedPassword 中。
  • matches 方法内部会自动解析盐值并复用加密参数,开发者无需关心细节。

总结

passwordEncoder.matches() 的核心是 “用密文中的盐值和参数重新加密原始密码,再对比哈希结果”,这保证了即使相同原始密码生成的密文不同(因盐值随机),仍能正确验证。这种机制既避免了盐值管理的复杂性,又保证了密码验证的安全性。

 

JWT无状态认证token 包含用户信息和过期时间

"token": "eyJhbGciOiJIUzUxMiJ9.eyJ1c2VySWQiOjEsInVzZXJuYW1lIjoic2hhb3plbWluZyIsInN1YiI6InNoYW96ZW1pbmciLCJpYXQiOjE3NTU2ODA3MDYsImV4cCI6MTc1NTY4MTYwNn0.e_2SZzCHe_9uFXYicpyfyf-AM2WCuhp3x5IRZVsEwjsuQyx1mJ_KI_DkNqKqgu6UxDgdULiwCArVVOP2G6XddQ",

 解码分析

(1)Header(头部)

解码字符串:eyJhbGciOiJIUzUxMiJ9
Base64 解码后为 JSON:

{"alg": "HS512"
}
  • 含义:声明该 JWT 使用 HS512 算法进行签名(与你之前代码中使用的算法一致)。
(2)Payload(载荷)

解码字符串:eyJ1c2VySWQiOjEsInVzZXJuYW1lIjoic2hhb3plbWluZyIsInN1YiI6InNoYW96ZW1pbmciLCJpYXQiOjE3NTU2ODA3MDYsImV4cCI6MTc1NTY4MTYwNn0
Base64 解码后为 JSON:

{"userId": 1,"username": "shaozeming","sub": "shaozeming","iat": 1755680706,"exp": 1755681606
}

(3)Signature(签名)

最后一部分是签名:e_2SZzCHe_9uFXYicpyfyf-AM2WCuhp3x5IRZVsEwjsuQyx1mJ_KI_DkNqKqgu6UxDgdULiwCArVVOP2G6XddQ

  • 作用:由头部指定的 HS512 算法,结合服务器端的密钥对 Header 和 Payload 进行签名生成,用于验证令牌的完整性和真实性(防止被篡改)。

  • 无法解码,仅能通过服务器端的密钥验证有效性。

http://www.dtcms.com/a/340907.html

相关文章:

  • K距离间隔重排字符串 (LeetCode 358) — Swift解法 + 可运行Demo
  • 360T7刷OpenWRT笔记
  • 深入解析EventPoller:Disruptor的轮询式事件处理机制
  • Download:几款主流的全球范围的NDVI产品参数说明和下载
  • Spring Boot 发展史
  • 机器学习——数据清洗
  • JS对象与JSON转换全解析
  • C/C++嵌入式笔试核心考点精解
  • AI 与 OCR 识别:深度融合的智能信息提取技术
  • Elasticsearch 写入全链路:从单机到集群
  • 实验8.20
  • nvidia最新论文:小型语言模型是代理人工智能的未来
  • iOS App 上架实战 从内测到应用商店发布的全周期流程解析
  • Linux 文件系统权限管理(补充)
  • 管理项目服务器连接数据库
  • Linux 文本处理三剑客:awk、grep、sed 完全指南
  • 中小型企业是否需要使用高防服务器
  • Linux-文本搜索工具grep
  • C++进阶-----C++11
  • Hangfire定时部署(.NET 8 + SQL Server)
  • Android 资源替换:静态替换 vs 动态替换
  • PHP特有的安全漏洞及渗透测试利用方法(通俗易懂)
  • 项目1总结其一
  • 49 C++ STL模板库18-类模板-pair
  • ROS 2系统Callback Group概念笔记
  • 突发!DeepSeek刚刚开源V3.1-Base
  • UTF-8 编解码可视化分析
  • 【Day 30】Linux-SQL语句
  • C/C++ 与嵌入式岗位常见笔试题详解
  • MYSQL为什么会发生死锁,怎么解决