Tomcat 8.5 DatasourceRealm SHA256摘要认证配置失败求助
我之前在配置Tomcat 8.5的SHA256摘要认证时也踩过类似的坑,结合你的描述,大概率是这几个关键环节没匹配上,咱们一步步来排查解决:
1. 确认CredentialHandler与Realm的绑定配置
首先要确保你的Realm正确关联了MessageDigestCredentialHandler,并且参数和生成摘要时完全一致。比如你的DataSourceRealm配置应该是这样的:
<Realm className="org.apache.catalina.realm.DataSourceRealm" dataSourceName="jdbc/MyDB" userTable="users" userNameCol="username" userCredCol="digest" userRoleTable="user_roles" roleNameCol="role"> <CredentialHandler className="org.apache.catalina.realm.MessageDigestCredentialHandler" algorithm="SHA-256" encoding="UTF-8" iterations="1"/> </Realm>
这里要注意:
userCredCol必须指向你存储SHA256摘要的数据库字段algorithm、encoding要和你生成摘要时用的完全一致,尤其是编码别用GBK或者默认编码,必须指定UTF-8
2. 核对摘要生成的格式与Realm名称
Tomcat的Digest认证要求摘要必须是用户名:领域名:密码的组合哈希,这里的领域名(realmName)必须完全匹配:
- 如果你的web.xml里配置了
<login-config>,那领域名就是里面的<realm-name>值:<login-config> <auth-method>DIGEST</auth-method> <realm-name>MyAppRealm</realm-name> <!-- 这个值要和生成摘要时的一致 --> </login-config> - 如果没在web.xml指定,Tomcat会用Realm的
realmName属性值(默认是UserDatabase,但自定义Realm最好显式设置)
举个例子,假设用户是venkat,领域名是MyAppRealm,密码是test123,那生成摘要的原始字符串必须是venkat:MyAppRealm:test123,不能有任何拼写错误、大小写差异。
3. 确保数据库存储的是十六进制字符串
很多工具生成SHA256时默认输出Base64编码,但Tomcat的MessageDigestCredentialHandler默认是读取十六进制格式的摘要。你可以用这段Java代码生成正确的十六进制摘要:
import java.security.MessageDigest; import java.nio.charset.StandardCharsets; public class DigestGenerator { public static void main(String[] args) throws Exception { String rawInput = "venkat:MyAppRealm:test123"; // 替换成你的实际组合 MessageDigest md = MessageDigest.getInstance("SHA-256"); byte[] digestBytes = md.digest(rawInput.getBytes(StandardCharsets.UTF_8)); // 转成十六进制字符串 StringBuilder hexDigest = new StringBuilder(); for (byte b : digestBytes) { hexDigest.append(String.format("%02x", b)); } System.out.println(hexDigest.toString()); } }
把这个输出的字符串存入数据库的digest字段,不要存Base64或者其他格式。
4. 开启Tomcat调试日志排查
如果上面的配置都没问题,就开启Tomcat的Realm调试日志,看具体哪里不匹配:
在conf/logging.properties里添加一行:
org.apache.catalina.realm.level = FINE
重启Tomcat后,查看localhost.log,里面会打印Tomcat计算的摘要值和从数据库读取的值,对比这两个就能找到差异点。
5. 用curl排除浏览器问题
有些现代浏览器可能对Digest认证支持有问题,你可以用curl测试认证是否正常:
curl -v --digest -u venkat:test123 http://localhost:8080/你的应用路径/受保护资源
如果curl能成功认证,那问题大概率出在浏览器配置;如果curl也失败,就回到前面的步骤核对配置。
内容的提问来源于stack exchange,提问作者venkat

