📌AI人工智能: 「AI大模型」AI_Agent智能体实战项目保姆级文档
📋 目录
- 一、工具类功能
- 二、所需环境
- 三、方法与调用示例(按需调用)
- 四、工具类源码(可直接复制)
一、工具类功能
注册时用随机盐 + PBKDF2-HMAC-SHA256 拉伸出一个慢哈希,连同算法、迭代次数、盐一起编进一个自描述串存库,登录时把整串交给 verify 比对,明文口令永不出库。
二、所需环境
JDK 17或以上
三、方法与调用示例(按需调用)
🔢方法序号:1
🎯方法用途:
- 用默认参数(PBKDF2-HMAC-SHA256、60 万次迭代、16 字节随机盐)把口令算成一条落库串
- 算法、迭代次数、盐都编在串里,登录时不用再存别的字段
🧩方法定义:public static String hash(String password)
🗣️入参解释:public static String hash(明文口令)
📤返回值解释:String,形如$pbkdf2-sha256$600000$盐$哈希的自描述串
💡边界口径:
- 盐每次随机,同一个口令两次生成的串不同,但都能被方法4 验过
- 默认 60 万次迭代实测约 346 毫秒,是 CPU 密集操作,只在注册与改密时调,别放进请求主链路
- 口令为
null抛IllegalArgumentException: 口令不能为null,空串抛IllegalArgumentException: 口令不能为空串 - JVM 缺 PBKDF2 实现时抛
IllegalStateException,不会退回弱方案
🧪方法示例:
hash(\"Passw0rd!\")拿到以$pbkdf2-sha256$打头、总长91字符的串- 同一口令连调两次
hash(...),两个串相同拿到false,盐是随机的 hash(null)抛IllegalArgumentException: 口令不能为nullhash(\"\")抛IllegalArgumentException: 口令不能为空串
🔢方法序号:2
🎯方法用途:
- 生成口令哈希串并指定迭代次数,跑测试、压参数时把成本降下来
- 迭代次数写在串里,日后提到默认值也不影响老串继续验证
🧩方法定义:public static String hash(String password, int iterations)
🗣️入参解释:public static String hash(明文口令, 迭代次数)
📤返回值解释:String,口令哈希串
💡边界口径:
- 迭代次数必须落在
[1000, 10000000],越界抛IllegalArgumentException,消息带区间、当前值和「生产建议使用600000」 - 盐仍是每次随机,所以同一口令同一轮数两次结果也不同
- 低轮数只适合测试,落库生产别调低
🧪方法示例:
hash(\"Passw0rd!\", 10000)生成的串以$pbkdf2-sha256$10000$打头- 同一参数连调两次
hash(...),两个串相同拿到false hash(\"Passw0rd!\", 999)抛IllegalArgumentException,消息是「迭代次数必须落在 [1000, 10000000] 区间,当前为999,生产建议使用600000」hash(\"Passw0rd!\", 10000001)抛IllegalArgumentException,同样带区间与当前值
🔢方法序号:3
🎯方法用途:
- 完整控制参数生成落库串:迭代次数、盐长度、派生长度都由你给
- 对接有硬性参数规定的老系统、或要把派生长度调到 512 位时用它
🧩方法定义:public static String hash(String password, int iterations, int saltBytes, int keyBits)
🗣️入参解释:public static String hash(明文口令, 迭代次数, 盐字节长度, 派生长度)
📤返回值解释:String,五段式的口令哈希串
💡边界口径:
- 盐长度不得小于 8 字节,抛错时消息直接写「盐长度不得小于8字节,当前为4」
- 派生长度必须是 8 的倍数且落在
[128, 512]位区间,255 和 520 都被拒 - 参数改大,串的段数仍是 5 段,只是长度变长
- 默认口径是盐 16 字节、派生 256 位,方法1 就是这套参数
🧪方法示例:
hash(\"Passw0rd!\", 10000, 24, 512)拿到5段的串hash(\"p\", 10000, 4, 256)抛IllegalArgumentException: 盐长度不得小于8字节,当前为4hash(\"p\", 10000, 16, 255)抛IllegalArgumentException,消息是「派生长度必须是8的倍数且落在 [128, 512] 位区间,当前为255」hash(\"p\", 10000, 16, 520)抛IllegalArgumentException,同样带上「当前为520」
🔢方法序号:4
🎯方法用途:
- 校验明文口令与库里的哈希串是否匹配,迭代次数、盐、派生长度全部从串里解析
- 登录只要交口令和存串,不需要当初生成时用了什么参数
🧩方法定义:public static boolean verify(String password, String storedHash)
🗣️入参解释:public static boolean verify(待校验口令, 存储串)
📤返回值解释:boolean,匹配为true,不匹配为false
💡边界口径:
- 口令为
null或空串一律返回false,不抛异常,不给攻击者区分「用户不存在」和「口令错」的机会 - 存储串为
null或空白抛IllegalArgumentException: 口令哈希串不能为null或空白 - 串格式非法、方案不认识、迭代次数越界抛
IllegalArgumentException,消息里带上实际拿到的串(过长会截断并标出长度) - 每次验证都要跑完串里记录的迭代次数,默认串一次约几百毫秒,登录接口要按这个成本限流
🧪方法示例:
verify(\"Passw0rd!\", storedHash)口令正确拿到true- 末尾一个字符改成
?拿到false verify(null, storedHash)拿到false- 换成空串口令,拿到的仍是
false - 同一口令换一条用相同参数另生成的串,仍拿到
true verify(\"Passw0rd!\", null)抛IllegalArgumentException: 口令哈希串不能为null或空白
🔢方法序号:5
🎯方法用途:
- 判断一条存储串是否该按当前默认参数重算,登录成功后顺手升级
- 把迭代次数从 10 万提到 60 万这类调整,靠它在用户无感时逐条换掉旧串
🧩方法定义:public static boolean needsRehash(String storedHash)
🗣️入参解释:public static boolean needsRehash(存储串)
📤返回值解释:boolean,需要重算为true
💡边界口径:
- 迭代次数低于默认值、盐长度或派生长度不合当前口径,都算需要重算
- 串本身不合法(脏数据、别的方案写的)也返回
true,让调用方在下次登录时把它修掉,而不是抛异常打断登录 - 判读只解析串头,不跑 PBKDF2 派生,成本极低
- 与
verify配合的标准写法是:验口令通过且needsRehash为true时,用原口令重新hash回写
🧪方法示例:
needsRehash(storedHash)对默认参数生成的串拿到false- 对 1 万次迭代的历史串拿到
true needsRehash(null)拿到true,脏串同样算需要重算needsRehash(\"$pbkdf2\")拿到true
🔢方法序号:6
🎯方法用途:
- 按指定的目标迭代次数判断要不要重算
- 灰度调参时先只把一部分账号升到新轮数,用它按目标值筛账号
🧩方法定义:public static boolean needsRehash(String storedHash, int targetIterations)
🗣️入参解释:public static boolean needsRehash(存储串, 目标迭代次数)
📤返回值解释:boolean,需要重算为true
💡边界口径:
- 串的迭代次数与目标值一致就返回
false,只比迭代次数,不看盐和派生长度 - 目标值比串里记的高,返回
true - 串不合法同样返回
true,方法5 的兜底口径在这延续
🧪方法示例:
needsRehash(1 万次迭代串, 10000)拿到false,目标与串一致needsRehash(1 万次迭代串, 20000)拿到true,目标更高需要升级needsRehash(默认串, 1000000)拿到true,默认 60 万次也够不上这个目标
🔢方法序号:7
🎯方法用途:
- 只解析存储串的迭代次数、盐与哈希,不跑派生,拿到一个
Params记录 - 巡检「还有多少账号是低迭代存的」、迁移前统计方案分布,用它只读不校验
🧩方法定义:public static Params parse(String storedHash)
🗣️入参解释:public static Params parse(存储串)
📤返回值解释:Params,public record Params(int iterations, byte[] salt, byte[] hash),盐和哈希都是防御性副本
💡边界口径:
salt()与hash()每次返回新副本,改掉它不会影响记录内部,也不会污染下一次读取- 它不做口令校验,要验证一律走方法4
- 串格式非法、方案不认识、迭代次数越界抛
IllegalArgumentException - 解析成本极低,只切串和 Base64 解码
🧪方法示例:
parse(storedHash).iterations()对 1 万次迭代的串拿到10000parse(storedHash).salt().length拿到16字节parse(storedHash).hash().length拿到32字节- 把
salt()返回的数组整体置零,再取一次与它相同拿到false,每次交出的都是副本 parse(\"$pbkdf2\")抛IllegalArgumentException,消息是「口令哈希串格式不合法,应为p b k d f 2 − s h a 256 pbkdf2-sha256pbkdf2−sha256迭代数盐 盐盐哈希,实际为: $pbkdf2」
🔢方法序号:8
🎯方法用途:
- 判断一段字符串是不是本类的口令哈希格式,不做解析也不做校验
- 导入历史用户、迁移前挑出没升级的账号时,用它一眼分类
🧩方法定义:public static boolean isStoredFormat(String storedHash)
🗣️入参解释:public static boolean isStoredFormat(待判断字符串)
📤返回值解释:boolean,是本类格式返回true
💡边界口径:
null、空串、普通 SHA-256 摘要串都返回false,不抛异常- 只看五段结构与方案名,不保证这串真能验过某个口令
- 想拿参数用
parse,想判是否该升级用needsRehash
🧪方法示例:
isStoredFormat(hash(\"Passw0rd!\"))拿到trueisStoredFormat(64 位 SHA-256 摘要串)拿到falseisStoredFormat(null)拿到falseisStoredFormat("")传空串拿到false
四、工具类源码(可直接复制)
📦本工具类源码:93-密码加盐哈希存储工具类
📦 需要「Java企业级工具类全家桶(1-100)」点点关注点点赞,回复「java工具类」可领取100个工具类的完整源码
💡 工具类已调试通过,复制粘贴即可使用,省时省力
💡 可保存到自己网盘,永久有效
觉得对您有帮助,麻烦点点关注啦,您的关注是我创作的最大动力~ 🎯