【问题标题】:Using TFS Rest API works from curl but not from client dotnet library使用 TFS Rest API 适用于 curl 但不适用于客户端 dotnet 库
【发布时间】:2020-05-08 20:08:07
【问题描述】:

我正在使用库 Microsoft.VisualStudio.Services.Client 中的以下代码:

var credential = new VssBasicCredential("", "<PAT>");
var url = "<url>"";
using var vssConnection = new VssConnection(new Uri(url), credential);
await vssConnection.ConnectAsync();

它失败并出现以下异常,我认为这与服务器不允许基本身份验证有关:

System.ComponentModel.Win32Exception (0x80090020): GSSAPI operation failed with error - Unspecified GSS failure.  Minor code may provide more information (SPNEGO cannot find mechanisms to negotiate).
   at System.Net.NTAuthentication.GetOutgoingBlob(Byte[] incomingBlob, Boolean throwOnError, SecurityStatusPal& statusCode)
   at System.Net.NTAuthentication.GetOutgoingBlob(String incomingBlob)
   at System.Net.Http.AuthenticationHelper.SendWithNtAuthAsync(HttpRequestMessage request, Uri authUri, ICredentials credentials, Boolean isProxyAuth, HttpConnection connection, HttpConnectionPool connectionPool, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithNtConnectionAuthAsync(HttpConnection connection, HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.AuthenticationHelper.SendWithAuthAsync(HttpRequestMessage request, Uri authUri, ICredentials credentials, Boolean preAuthenticate, Boolean isProxyAuth, Boolean doRequestAuth, HttpConnectionPool pool, CancellationToken cancellationToken)
   at System.Net.Http.DecompressionHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.DiagnosticsHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at Microsoft.VisualStudio.Services.Common.VssHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at Microsoft.VisualStudio.Services.Common.VssHttpRetryMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
   at Microsoft.VisualStudio.Services.WebApi.VssHttpClientBase.SendAsync(HttpRequestMessage message, HttpCompletionOption completionOption, Object userState, CancellationToken cancellationToken)
   at Microsoft.VisualStudio.Services.WebApi.VssHttpClientBase.SendAsync[T](HttpRequestMessage message, Object userState, CancellationToken cancellationToken)
   at Microsoft.VisualStudio.Services.Location.Client.LocationHttpClient.GetConnectionDataAsync(ConnectOptions connectOptions, Int64 lastChangeId, CancellationToken cancellationToken, Object userState)
   at Microsoft.VisualStudio.Services.WebApi.Location.VssServerDataProvider.GetConnectionDataAsync(ConnectOptions connectOptions, Int32 lastChangeId, CancellationToken cancellationToken)
   at Microsoft.VisualStudio.Services.WebApi.Location.VssServerDataProvider.ConnectAsync(ConnectOptions connectOptions, CancellationToken cancellationToken)

但是,我设法从命令行成功执行 REST 命令

curl <url>/_apis/projects -u :<PAT>

我正在使用无法修改任何配置的 Azure Devops Server 2019。我正在运行 dotnet-core Alpine docker 映像中的代码。

是 dotnet 库的限制还是我用错了?

【问题讨论】:

  • 为什么要使用ConnectAsync方法?你想用哪个rest api?
  • 这就是我在示例中看到的。你说我应该跳过它?我正在尝试在GitHttpClient 下使用 api - 获取项目、获取存储库等
  • 我没用,只是vssConnection.GetClient&lt;GitHttpClient&gt;();
  • @ShaykiAbramczyk 此调用产生完全相同的错误

标签: c# tfs azure-devops-rest-api azure-devops-server-2019 azure-devops-server


【解决方案1】:

我收到此错误,AccessToken 已过期。

通过curl 验证了这一点。

创建一个新的令牌后它工作了。

【讨论】:

    【解决方案2】:

    我在 Docker 容器中运行的程序中遇到了同样的错误。原因是 PAT 过期。这在错误消息中不是很清楚(“SPNEGO 找不到协商机制”)。此外,过期的 PAT 在我的开发机器上仍然有效。这就是为什么我什至不认为 PAT 可能已经过期了。

    新生成的 PAT:一切都在运行。

    【讨论】:

    • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
    【解决方案3】:

    如果你想使用 GitHttpClient,正如@Shayki Abramczyk 指出的,你应该使用vssConnection.GetClient&lt;GitHttpClient&gt;() 来获取 GitHttpClient 连接。

    var credential = new VssBasicCredential("", "<PAT>");
    var url = "<url>"";
    using var vssConnection = new VssConnection(new Uri(url), credential);
    GitHttpClient gitClient = vssConnection.GetClient<GitHttpClient>();
    

    您可以按照 Microsoft 文档中 QuickStarts and Samples 中的示例进行操作

    【讨论】:

    • 你可以尝试安装 gss-ntlmssp 并设置 AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false) 如hread中所述
    • 谢谢,我在尝试安装时发现了问题gss-ntlmssp
    【解决方案4】:

    问题在于 dotnet Docker 映像的 Alpine 发行版,它尚不支持 gss-ntlmssp。切换到标准映像(基于 Ubuntu - mcr.microsoft.com/dotnet/core/aspnet:3.1)解决了这个问题。

    【讨论】:

      猜你喜欢
      • 2017-06-25
      • 1970-01-01
      • 1970-01-01
      • 2017-05-16
      • 1970-01-01
      • 2013-05-29
      • 2020-04-06
      • 2015-01-21
      • 1970-01-01
      相关资源
      最近更新 更多