Eclipse EGit TFS Git 连接 - 不支持身份验证

Eclipse EGit TFS Git Connection - Authentication not supported

嗨,

我们在使用 eclipse 中的 egit 时遇到了“不支持身份验证”这个可怕的问题。我已经阅读了很多文章和问题,但其中 none 似乎解决了手头的问题。

我们正在使用 Microsoft Team Foundation Server 2015,它可以提供 git 存储库作为版本控制系统。但是身份验证机制似乎无法使用 eclipse 的 egit 插件。我们检查了使用来自 eclipse 2020-06、2020-12、2021-03 的不同 eclipse 版本以及不同的 jdk 设置 1.8、11 和 15 但没有成功。

克隆,push/fetch 与 git 命令行(git bash - windows)一起工作正常,即使是遗留的 eclipse kepler 也可以正常工作,没有问题,但不是最新的。该问题似乎与 NTLM 身份验证有关。在较新版本的 Eclipse 中,egit 不会协商或发送 NTLM 令牌,即使服务器响应 WWW-Authenticate: NTLM。

以下是新旧 eclipse 版本的详细信息,通过 TCP/IP 监视器进行流量捕获。 TFS git 存储库克隆协议是 http,即使门户位于 https。

日食 2021-03

要求:

GET /tfs/xxx/_git/xxx/info/refs?service=git-upload-pack HTTP/1.1
Accept-Encoding: gzip
Pragma: no-cache
User-Agent: JGit/5.11.0.202103091610-r
Accept: application/x-git-upload-pack-advertisement, */*
Git-Protocol: version=2
Host: tfs-xxx-xx:8090
Connection: Keep-Alive

响应:

HTTP/1.1 401 Unauthorized
Cache-Control: private
Content-Type: text/html
Server: Microsoft-IIS/8.5
X-TFS-ProcessId: 76ec3355-4bc2-498d-ba64-xxxxxxx
X-FRAME-OPTIONS: SAMEORIGIN
Access-Control-Allow-Origin: *
Access-Control-Max-Age: 3600
Access-Control-Allow-Methods: OPTIONS,GET,POST,PATCH,PUT,DELETE
Access-Control-Expose-Headers: ActivityId,X-TFS-Session
Access-Control-Allow-Headers: authorization
Set-Cookie: Tfs-SessionId=3b370bd6-2197-xxxxxxxxx; path=/
Set-Cookie: Tfs-SessionActive=2021-05-11T17:25:24; path=/
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
P3P: CP="CAO xxxxxxxxxxxxxxxxx"
X-Content-Type-Options: nosniff
Date: Tue, 11 May 2021 17:25:24 GMT
Content-Length: 1293

日食开普勒

第一个Request/Response和上面类似

第二个请求:

GET /tfs/xxx/_git/xxx/info/refs?service=git-upload-pack HTTP/1.1
Accept-Encoding: gzip
Pragma: no-cache
User-Agent: JGit/3.2.0.201312181205-r
Accept: application/x-git-upload-pack-advertisement, */*
Cache-Control: no-cache
Host: tfs-pmo-app:8090
Connection: keep-alive
Authorization: NTLM TlRMTVxxxxxxx - Length 72 chars

第二个回复:

HTTP/1.1 401 Unauthorized
Content-Type: text/html; charset=us-ascii
WWW-Authenticate: NTLM TlRMxxxxxx== - Length 354 chars
Server: Microsoft-HTTPAPI/2.0
Date: Tue, 11 May 2021 17:33:00 GMT
Content-Length: 341

第三个请求:

GET /tfs/xxx/_git/xxx/info/refs?service=git-upload-pack HTTP/1.1
Accept-Encoding: gzip
Pragma: no-cache
User-Agent: JGit/3.2.0.201312181205-r
Accept: application/x-git-upload-pack-advertisement, */*
Cache-Control: no-cache
Host: tfs-pmo-app:8090
Connection: keep-alive
Authorization: NTLM TlRMTVNxxxxx - Length 256 chars

第三个回复:

HTTP/1.1 200 OK
Cache-Control: private
Content-Type: application/x-git-upload-pack-advertisement
Server: Microsoft-IIS/8.5
X-TFS-ProcessId: 76ec3355-4bc2-xxxxxxxxxxxxxx
X-FRAME-OPTIONS: SAMEORIGIN
Access-Control-Allow-Origin: *
Access-Control-Max-Age: 3600
Access-Control-Allow-Methods: OPTIONS,GET,POST,PATCH,PUT,DELETE
Access-Control-Expose-Headers: ActivityId,X-TFS-Session
Access-Control-Allow-Headers: authorization
Set-Cookie: Tfs-SessionId=xxxxxxxxxxxx; path=/
Set-Cookie: Tfs-SessionActive=2021-05-11T17:33:01; path=/
X-VSS-UserData: 69b58752-xxxxxxxxxxxxx
X-AspNet-Version: 4.0.30319
Persistent-Auth: true
X-Powered-By: ASP.NET
P3P: CP="CAO xxxxxxxxxxxxxxxxxxxxxxxxx"
X-Content-Type-Options: nosniff
Date: Tue, 11 May 2021 17:33:00 GMT
Content-Length: 1098

到目前为止我们已经尝试过,将连接超时增加到 300,在 Eclipse 首选项中为 Git 更改 http 客户端,在克隆 repo 时添加 username/password - 这没有任何可见的影响,使用 jdk 更改 eclipse 的不同变体,将 git 凭据帮助器更改为 wincred,管理器,甚至在没有任何凭据帮助器的情况下重置存储,尝试配置 cntlm 但在测试期间它说您不需要代理,none 这似乎有效。

这可能意味着 egit/jgit 实现中存在错误。从错误中查看当前实现源和跟踪堆栈:

!ENTRY org.eclipse.egit.core 4 0 2021-05-08 04:56:02.018
!MESSAGE Pulling 1 repository
!SUBENTRY 1 org.eclipse.egit.core 4 0 2021-05-08 04:56:02.021
!MESSAGE http://xxxxx:8090/tfs/xxxx/_git/xxx: authentication not supported
!STACK 0
org.eclipse.jgit.api.errors.TransportException: http://xxxxx:8090/tfs/xxxx/_git/xxx: authentication not supported
    at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:224)
    at org.eclipse.jgit.api.PullCommand.call(PullCommand.java:263)
    at org.eclipse.egit.core.op.PullOperation$PullJob.run(PullOperation.java:255)
    at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)
Caused by: org.eclipse.jgit.errors.TransportException: http://xxxxx:8090/tfs/xxxx/_git/xxx: authentication not supported
    at org.eclipse.jgit.transport.TransportHttp.connect(TransportHttp.java:674)
    at org.eclipse.jgit.transport.TransportHttp.openFetch(TransportHttp.java:465)
    at org.eclipse.jgit.transport.FetchProcess.executeImp(FetchProcess.java:142)
    at org.eclipse.jgit.transport.FetchProcess.execute(FetchProcess.java:94)
    at org.eclipse.jgit.transport.Transport.fetch(Transport.java:1309)
    at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:213)
    ... 3 more

https://git.eclipse.org/r/plugins/gitiles/jgit/jgit/+/refs/tags/v5.11.0.202103091610-r/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java

org.eclipse.jgit.transport.TransportHttp.connect(TransportHttp.java:674):

Line 671:   case HttpConnection.HTTP_UNAUTHORIZED:
Line 672:                       authMethod = HttpAuthMethod.scanResponse(conn, ignoreTypes);
Line 673:                       if (authMethod.getType() == HttpAuthMethod.Type.NONE)
Line 674:                           throw new TransportException(uri, MessageFormat.format(
Line 675:                                   JGitText.get().authenticationNotSupported, uri));

看起来 scanResponse 方法正在为导致问题的身份验证方法类型返回 none,所以让我们回顾一下 HttpAuthMethod:

https://git.eclipse.org/r/plugins/gitiles/jgit/jgit/+/refs/tags/v5.11.0.202103091610-r/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpAuthMethod.java

这里的代码基本上检查了 3 种身份验证方法,BASIC、DIGEST 和 NEGOTIATE,在我们的例子中 header "WWW-Authenticate: NTLM" 是支持的一次的 none 因此异常。

但令人困惑的部分是 kepler 到底是如何成功地为 NTLM 进行身份验证的,答案可能(通过 web-searches)实际上 jdk 可能对此负责,因为它在 HttpURLConnection class 固有地发送 NTLM 令牌,对于更新的 jdks 可能不是这种情况(不知道为什么)。

结论:我好像没有找到问题出在哪里的正确答案?

  1. 是否因为新的 jdks 本身不支持 NTML(在 罩)?
  2. 不应该 egit/jgit 退回到其他机制,如 BASIC 身份验证?
  3. 为什么我不能使用 pre-emptively 发送我的凭据 egit/jgit 绕过 NTLM?

P.S. 写这个 post 时,看起来我们的服务器可能没有配置 BASIC 身份验证支持,但我尝试了不同的身份验证使用 git 命令输入,它们确实有效。我将再次使用 wireshark 捕获检查并查看底层机制。

谢谢,如果你读完整个post :)。

Eclipse EGit TFS Git Connection - Authentication not supported

我同意你的看法。据我所知,Eclipse 的 EGit 是基于 JGit 构建的,不幸的是,最新版本的 JGit 主动拒绝 NTLM 身份验证,导致在连接到需要 NTLM 的本地安装的 TFS 时出现“不支持身份验证”。

您可以从FAQ获得更多解释和解决方案:

  • Use Cntlm, a locally-installed proxy that adds NTLM authentication on-the-fly

  • Use an older version of Eclipse/EGit/JGit

  • Enable basic authentication with SSL in IIS on your TFS server

  • Enable Kerberos authentication in IIS on your TFS server (the default for the next version of TFS after TFS 2015):

    1. In IIS manager, click on the TFS site on the left under Connections and open up the "Authentication" section under IIS. Set “ASP.NET Impersonation” to Enabled and “Windows Authentication” to Enabled.

    2. Under "Windows Authentication" right click and select "Providers." Add/enable the "Negotiate" and "NTLM" providers.

    3. Under "Windows Authentication" right click and select "Advanced Settings." Uncheck "Enable Kernel-mode" because it is incompatible with Kerberos.

此外,使用 TFS 2017 RTW 及更高版本,您可以创建范围至少为代码(读取和写入)的 Personal Access Token,然后您可以在 Eclipse EGit 配置中使用它代替密码。

我终于设法解决了这个问题。

由于开普勒版本 (jdk 1.7) 能够与 tfs 通信,所以我查看了 1.7 之后的 jdks 是否有什么变化,幸运的是:

How to provide ntlm authentication while calling any url?

从 jdk1.8.0_181 开始,默认禁用基于 http 的 ntlm 透明身份验证,因此只需将其设置为 allHosts 即可解决问题。

您需要做的就是在 jre/lib/net.properties 文件中注释此行 Java 8,或 /conf/net.properties [=37] =] 11/15:

#jdk.http.ntlm.transparentAuth=disabled

并取消注释这个:

jdk.http.ntlm.transparentAuth=allHosts

您也可以使用“-Djdk.http.ntlm.transparentAuth=allHosts”作为 jvm 参数进行设置。

此外,由于这适用于 HttpUrlConnection jdk 本机客户端,因此我们还需要更改 git http 客户端配置以使用“Java 内置 HTTP”而不是“Apache HTTP” ".

转到您的 github 帐户并创建一个新的个人访问令牌(Settings/Developer 设置)并在身份验证对话框出现时使用它来输入用户名和密码。提供令牌代替密码。你的推动会发生。在此之前,还要为您的 github 帐户启用 2 因素身份验证。