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

问题描述 投票:0回答:1

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

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

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

Chrome 请求

[truncated]Authorization: Negotiate YIIIsgYGKwYBBQUCoIIIpjCC...
    GSS-API Generic Security Service Application Program Interface
        OID: 1.3.6.1.5.5.2 (SPNEGO - Simple Protected Negotiation)
        Simple Protected Negotiation
            negTokenInit
                mechTypes: 4 items
                mechToken: 6082086406092a864886f71201020201006e820853308208…
                krb5_blob: 6082086406092a864886f71201020201006e820853308208…
                    KRB5 OID: 1.2.840.113554.1.2.2 (KRB5 - Kerberos 5)
                    krb5_tok_id: KRB5_AP_REQ (0x0001)
                    Kerberos

=> Chrome 响应状态

HTTP/1.1 302 Found 

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

这是

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

 [truncated]Authorization: Negotiate YIIHQQYJKoZIhvcSAQICAQBuggcw...
    GSS-API Generic Security Service Application Program Interface
        OID: 1.2.840.113554.1.2.2 (KRB5 - Kerberos 5)
        krb5_blob: 01006e8207303082072ca003020105a10302010ea2070305…
            krb5_tok_id: KRB5_AP_REQ (0x0001)
            Kerberos

=> 回复状态

HTTP/1.1 401 Unauthorized  (text/html)

我现在的测试代码是:

# 302 response is already handled by the first GET
r1 = session.get(url)  
    if r1.status_code != 401:
        print("Error! Server authorization failed at step 2. Expected response 401 but instead got: " + str(r1.status_code))
        return None
auth_url = r1.url
# step 2: server sends 401 and WWW-Authenticate: Negotiate header
# GSS-API (SPNEGO - Simple Protected Negotiation)
r2 = session.get(auth_url, auth=HTTPSPNEGOAuth(mutual_authentication=True))

使用 requests-gssapi 库让我最接近,但身份验证仍然失败。我不懂为什么。使用的 Kerberos 票证是相同的。我能看到成功的 Chrome 请求和失败的 python 请求之间的唯一区别是

OID
。但是我不知道如何改变它,因为它似乎是一个库实现细节。

如有任何帮助,我们将不胜感激。

python python-requests kerberos
1个回答
5
投票

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

  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
  4. 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)
完成了!

© www.soinside.com 2019 - 2024. All rights reserved.