Quarkus Security-JPA自定义PasswordProvider认证异常求助
解决Quarkus自定义PasswordProvider导致二次哈希的认证问题
你的核心问题是误解了PasswordProvider的职责:它不是用来哈希用户输入的明文密码,而是负责将数据库中已存储的哈希密码,转换为WildFly Security能识别的Password对象,供框架完成密码比对。
问题流程拆解
当前你的代码逻辑完全颠倒:
- 框架从数据库取出存储的哈希密码,传给
CustomPasswordProvider.getPassword() - 你对这个已哈希的密码再次执行哈希操作,生成新的
Password对象 - 框架拿用户输入的明文密码和这个二次哈希的对象比对,自然匹配失败返回401
修正方案
1. 重新实现CustomPasswordProvider
getPassword()的入参是数据库中存储的哈希字符串,你的任务是解析这个字符串,生成对应算法的Password实例,而不是再次哈希。
假设你用SCrypt算法,数据库中存储的是SCrypt格式的哈希值,修正后的Provider代码如下:
import org.wildfly.security.password.Password; import org.wildfly.security.password.PasswordProvider; import org.wildfly.security.password.interfaces.ScryptPassword; public class CustomPasswordProvider implements PasswordProvider { @Override public Password getPassword(String storedScryptHash) { // 解析SCrypt哈希字符串(格式示例:$s0$e0801$salt$digest) String[] parts = storedScryptHash.split("\\$"); int cost = Integer.parseInt(parts[2].substring(1)); // 提取cost参数 byte[] salt = parts[3].getBytes(); // 提取盐 byte[] digest = parts[4].getBytes(); // 提取存储的哈希值 // 创建WildFly Security的ScryptPassword实例 return ScryptPassword.createRaw( ScryptPassword.ALGORITHM_SCRYPT, salt, cost, 8, // blockSize,根据你的SCrypt配置调整 1, // parallelism,根据你的SCrypt配置调整 digest ); } }
2. 确认实体类注解匹配
确保@Password注解的配置和Provider逻辑一致:
@Column(name = "PWD_CRYPT") @Password(value = PasswordType.CUSTOM, provider = CustomPasswordProvider.class) public String password;
正确的认证流程
- 用户发送Basic Auth请求,框架提取请求头中的明文密码
- 框架通过
@UserDefinition从数据库查询到对应用户,取出存储的SCrypt哈希密码 - 调用
CustomPasswordProvider.getPassword(存储的哈希),生成ScryptPassword对象 - 框架使用WildFly Security的密码验证逻辑,将用户输入的明文密码与
ScryptPassword对象进行匹配(自动用SCrypt算法重新计算哈希并对比) - 匹配成功则通过认证,失败返回401
内容的提问来源于stack exchange,提问作者Christian Kölle
相关产品推荐
相关产品推荐

