无法在 SPNEGO 服务器上使用 requests-gssapi 进行身份验证

cap*_*tan 2 python kerberos python-requests

我尝试使用请求通过 python 访问公司 Intranet 上的 SAS 服务,但由于身份验证失败 (401),我无法使其工作。

\n\n

我在 Windows 10 上使用 python 3.7.4,请求 2.22.0。到目前为止,我已经尝试/检查过:

\n\n
    \n
  • requests.get(follow_redirects=True)
  • \n
  • 使用HTTPBasicAuth(\'user\', \'pass\')HTTPDigestAuth()HttpNtlmAuth(\'user\', \'pass\')
  • \n
  • 与所有可能的参数组合一起使用requests_kerberos.HTTPKerberosAuth(),包括设置force_preemptive=True标志和principal=user@REALM。我已确认klist确实存在多张门票。
  • \n
  • 安装 MIT Kerberos 并使用requests_gssapi.HTTPSPNEGOAuth().
  • \n
  • 在 git bash 中使用curl 命令curl -i -L -v --negotiate --user "domain\\user:pswd" <protected_service_url>进行身份验证。
  • \n
  • 在 Internet Explorer/Chrome 中打开 url 显然是有效的。我不必在任何地方输入我的凭据,任何身份验证都是在幕后处理的。
  • \n
  • 包的交换遵循基本的 Kerberos 身份验证流程:请求受保护的服务,接收到身份验证服务的重定向,遵循重定向而不进行身份验证,获得 401 响应和质询www-authenticate: Negotiate,使用身份验证票证进行响应。
  • \n
  • 我检查了与Wireshark的包交换。这是来自 Chrome 的 HTTP 包的关键请求+响应身份验证部分(成功):
  • \n
\n\n

Chrome 请求

\n\n
[truncated]Authorization: Negotiate YIIIsgYGKwYBBQUCoIIIpjCC...\n    GSS-API Generic Security Service Application Program Interface\n        OID: 1.3.6.1.5.5.2 (SPNEGO - Simple Protected Negotiation)\n        Simple Protected Negotiation\n            negTokenInit\n                mechTypes: 4 items\n                mechToken: 6082086406092a864886f71201020201006e820853308208\xe2\x80\xa6\n                krb5_blob: 6082086406092a864886f71201020201006e820853308208\xe2\x80\xa6\n                    KRB5 OID: 1.2.840.113554.1.2.2 (KRB5 - Kerberos 5)\n                    krb5_tok_id: KRB5_AP_REQ (0x0001)\n                    Kerberos\n
Run Code Online (Sandbox Code Playgroud)\n\n

=> Chrome 响应状态

\n\n
HTTP/1.1 302 Found \n
Run Code Online (Sandbox Code Playgroud)\n\n

然后浏览器会自动重定向到该服务。

\n\n

这是requests_gssapi.HTTPSPNEGOAuth()不成功的请求:

\n\n
 [truncated]Authorization: Negotiate YIIHQQYJKoZIhvcSAQICAQBuggcw...\n    GSS-API Generic Security Service Application Program Interface\n        OID: 1.2.840.113554.1.2.2 (KRB5 - Kerberos 5)\n        krb5_blob: 01006e8207303082072ca003020105a10302010ea2070305\xe2\x80\xa6\n            krb5_tok_id: KRB5_AP_REQ (0x0001)\n            Kerberos\n\n
Run Code Online (Sandbox Code Playgroud)\n\n

=> 响应状态

\n\n
HTTP/1.1 401 Unauthorized  (text/html)\n
Run Code Online (Sandbox Code Playgroud)\n\n

我现在的测试代码是:

\n\n
[truncated]Authorization: Negotiate YIIIsgYGKwYBBQUCoIIIpjCC...\n    GSS-API Generic Security Service Application Program Interface\n        OID: 1.3.6.1.5.5.2 (SPNEGO - Simple Protected Negotiation)\n        Simple Protected Negotiation\n            negTokenInit\n                mechTypes: 4 items\n                mechToken: 6082086406092a864886f71201020201006e820853308208\xe2\x80\xa6\n                krb5_blob: 6082086406092a864886f71201020201006e820853308208\xe2\x80\xa6\n                    KRB5 OID: 1.2.840.113554.1.2.2 (KRB5 - Kerberos 5)\n                    krb5_tok_id: KRB5_AP_REQ (0x0001)\n                    Kerberos\n
Run Code Online (Sandbox Code Playgroud)\n\n

使用requests-gssapi库让我最接近,但身份验证仍然失败。我不懂为什么。使用的 Kerberos 票证是相同的。我可以看到成功的 Chrome 请求和失败的 python 请求之间的唯一区别是OID. 但是我不知道如何改变它,因为它似乎是一个库实现细节。

\n\n

任何帮助表示赞赏。

\n

cap*_*tan 6

我设法解决了这个问题。因此,对于面临类似问题的任何人,以下是我的步骤:

  1. 我使用了 python requests-gssapi这是requests-kerberos的更新版本,可以就地删除。
  2. 然而,这个库最初并不适用于我的身份验证案例。原因是选择了错误的身份验证机制: OID:1.2.840.113554.1.2.2(KRB5 - Kerberos 5)而不是OID:1.3.6.1.5.5.2(SPNEGO - 简单保护协商)。幸运的是,在未接受的拉取请求中已经有了解决方案(截至 2019 年 9 月)。将 gssapi_.py 复制到本地安装。
  3. 使用以下代码,如拉取请求更新的 README.rst中所述:
import gssapi
import requests
from requests_gssapi import HTTPSPNEGOAuth
try:
   spnego = gssapi.mechs.Mechanism.from_sasl_name("SPNEGO")
except AttributeError:
   spnego = gssapi.OID.from_int_seq("1.3.6.1.5.5.2")
gssapi_auth = HTTPSPNEGOAuth(mech=spnego)
r = requests.get("http://example.org", auth=gssapi_auth)
Run Code Online (Sandbox Code Playgroud)

并做了!