携带Kerberos票据请求受保护API仍返回401未授权求助
我尝试调用部署在Linux服务器Apache上的Flask API端点http://monarch.example.com:8080/,该端点受Kerberos认证保护。已通过kinit user初始化Kerberos,使用Python kerberos库获取票据并通过requests库将票据放入Authorization请求头,但请求仍返回401未授权响应,且确认Authorization头已填充有效值。
相关代码片段
__, krb_context = kerberos.authGSSClientInit("HTTP@monarch.example.com") kerberos.authGSSClientStep(krb_context, "") auth_header = ("Negotiate " + kerberos.authGSSClientResponse(krb_context)) headers = {"Authorization": auth_header}
Apache Kerberos配置(/etc/apache2/sites-available/monarch.conf)
<Directory /var/www/monarch> AuthType Kerberos AuthName "Acme Corporation" KrbAuthRealms EXAMPLE.COM KrbMethodNegotiate Off KrbSaveCredentials Off KrbVerifyKDC Off KrbMethodK5Passwd On # Krb5Keytab /etc/apache2/http.keytab Krb5keytab /etc/krb5.keytab Require user user@EXAMPLE.COM </Directory>
Kerberos主体列表
host/monarch.example.com@EXAMPLE.COM HTTP/monarch.example.com@EXAMPLE.COM K/M@EXAMPLE.COM kadmin/admin@EXAMPLE.COM kadmin/changepw@EXAMPLE.COM krbtgt/EXAMPLE.COM@EXAMPLE.COM user@EXAMPLE.COM root/admin@EXAMPLE.COM
/etc/krb5.keytab密钥列表
slot KVNO Principal ---- ---- --------------------------------------------------------------------- 1 2 host/monarch.example.com@EXAMPLE.COM 2 2 host/monarch.example.com@EXAMPLE.COM 3 2 HTTP/monarch.example.com@EXAMPLE.COM 4 2 HTTP/monarch.example.com@EXAMPLE.COM
排查步骤
1. 修复Apache协商认证开关配置
你的Apache配置中KrbMethodNegotiate Off,但代码使用的是Negotiate头(Kerberos GSSAPI协商认证方式),二者直接冲突——该配置会禁用票据认证,仅保留密码认证方式,导致你的票据请求被拒绝。
操作: 将KrbMethodNegotiate Off改为KrbMethodNegotiate On,重启Apache:
sudo systemctl restart apache2
2. 验证keytab文件权限
确保Apache进程(默认用户为www-data)能读取/etc/krb5.keytab:
ls -l /etc/krb5.keytab sudo chown root:www-data /etc/krb5.keytab sudo chmod 640 /etc/krb5.keytab
3. 核对主体KVNO一致性
检查keytab中HTTP/monarch.example.com的KVNO是否与KDC中该主体的KVNO一致:
- 查看KDC中主体的KVNO:
kadmin.local -q "getprinc HTTP/monarch.example.com@EXAMPLE.COM"
- 查看keytab中的KVNO:
klist -kte /etc/krb5.keytab
若不一致,重新生成keytab:
kadmin.local -q "ktadd -k /etc/krb5.keytab HTTP/monarch.example.com@EXAMPLE.COM"
4. 修正代码中的服务主体格式
将kerberos.authGSSClientInit的参数改为完整主体名,避免自动补全可能的错误:
__, krb_context = kerberos.authGSSClientInit("HTTP/monarch.example.com@EXAMPLE.COM")
5. 开启Apache调试日志定位问题
修改monarch.conf添加调试日志配置:
LogLevel debug
重启Apache后,查看错误日志(通常路径/var/log/apache2/error.log),搜索kerberos或negotiate关键词,获取具体失败原因。
6. 用curl排除代码层面问题
使用curl测试认证流程,确认服务端配置是否正常:
curl -v --negotiate -u : http://monarch.example.com:8080/
若curl请求成功,问题出在Python代码实现;若curl也失败,聚焦服务端Kerberos配置或票据有效性排查。
内容的提问来源于stack exchange,提问作者Renascence Tarafder Prapty

