【问题标题】:Unable to consume TFS 2015 API. Getting 401 unauthrozed error无法使用 TFS 2015 API。收到 401 未经授权的错误
【发布时间】:2020-03-22 07:04:39
【问题描述】:

我试过TFS 2015 REST API Authentication 但是,它提到了请求对象(因为我不能使用 javascript),不确定请求对象在哪里或它的类型。

我正在尝试传递查询 ID,代码应该执行查询并通过 API 获取结果。 该解决方案在我的本地工作,但是,在发布到服务器后它似乎不起作用。 我还检查了是否可以使用凭据从服务器访问 TFS。

我的代码如下:

    private HttpClientHandler GetTfsCredentials()
    {
        HttpClientHandler handler2 = new HttpClientHandler { UseDefaultCredentials = true };
        handler2.Credentials = new NetworkCredential("username", "password", "domain");
        return handler2;
    }
        private async Task<object> GetQueryResults(string queryId)
    {
        string tfsApiUrl = ConfigurationManager.AppSettings["TfsApiUrl"];
        string tfsProjectName = ConfigurationManager.AppSettings["TfsProjectName"];
        string TfsProjectGuid = ConfigurationManager.AppSettings["TfsProjectGuid"];

        //I tried both credentials and credentials2, but none of them working

        string credentials = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes($"{""}:{"password"}"));

        string credentials2 = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("domain\\username:password") );

        if (!string.IsNullOrEmpty(tfsApiUrl) && !string.IsNullOrEmpty(tfsProjectName)
            && !string.IsNullOrEmpty(Id))
        {
            log.Info("GetQueryResults:: Config values found");
            using (var client = new HttpClient(GetTfsCredentials()) { BaseAddress = new Uri(tfsApiUrl) })
            {
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials2);

                HttpResponseMessage response = client.GetAsync($"{tfsProjectName}/_apis/wit/wiql/{Id}").Result;

                log.Info("GetQueryResults:: response.ReasonPhrase" + response.ReasonPhrase.ToString());
                log.Info("GetQueryResults:: response" + response.ToString());
                log.Info("GetQueryResults:: response.IsSuccessStatusCode" + response.IsSuccessStatusCode.ToString());
                string workItemList = null;

                if (response.IsSuccessStatusCode)
                {
                    //do something
                }
            }
        }

        return null;

    }

我收到的错误是:

2020-03-20 16:17:35,382 INFO GetQueryResults:: response.ReasonPhrase Unauthorized
2020-03-20 16:17:35,382 INFO GetQueryResults:: responseStatus Code: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
  X-TFS-ProcessId: 115b5bba-0bf4-45e2-a3b2-2913ccc93f09
  ActivityId: bb21d947-99a3-44dc-bdb7-317d7af34934
  X-TFS-Session: bb21d947-99a3-44dc-bdb7-317d7af34934
  X-VSS-E2EID: bb21d947-99a3-44dc-bdb7-317d7af34934
  X-FRAME-OPTIONS: SAMEORIGIN
  X-TFS-SoapException: %3c%3fxml+version%3d%221.0%22+encoding%3d%22utf-8%22%3f%3e%3csoap%3aEnvelope+xmlns%3asoap%3d%22http%3a%2f%2fwww.w3.org%2f2003%2f05%2fsoap-envelope%22%3e%3csoap%3aBody%3e%3csoap%3aFault%3e%3csoap%3aCode%3e%3csoap%3aValue%3esoap%3aReceiver%3c%2fsoap%3aValue%3e%3csoap%3aSubcode%3e%3csoap%3aValue%3eUnauthorizedRequestException%3c%2fsoap%3aValue%3e%3c%2fsoap%3aSubcode%3e%3c%2fsoap%3aCode%3e%3csoap%3aReason%3e%3csoap%3aText+xml%3alang%3d%22en%22%3eTF400813%3a+The+user+%27CWOPA%5cSTCTCAPD006%24%27+is+not+authorized+to+access+this+resource.%3c%2fsoap%3aText%3e%3c%2fsoap%3aReason%3e%3c%2fsoap%3aFault%3e%3c%2fsoap%3aBody%3e%3c%2fsoap%3aEnvelope%3e
  X-TFS-ServiceError: TF400813%3a+The+user+%27CWOPA%5cSTCTCAPD006%24%27+is+not+authorized+to+access+this+resource.
  Server: Microsoft-IIS/8.5
  WWW-Authenticate: Bearer
  WWW-Authenticate: Negotiate
  WWW-Authenticate: NTLM
  X-Powered-By: ASP.NET
  P3P: CP="CAO DSP COR ADMa DEV CONo TELo CUR PSA PSD TAI IVDo OUR SAMi BUS DEM NAV STA UNI COM INT PHY ONL FIN PUR LOC CNT"
  Lfs-Authenticate: NTLM
  X-Content-Type-Options: nosniff
  Date: Fri, 20 Mar 2020 20:17:35 GMT
  Content-Length: 82
  Content-Type: text/plain; charset=utf-8
}
2020-03-20 16:17:35,382 INFO GetQueryResults:: response.IsSuccessStatusCode False

【问题讨论】:

    标签: azure-devops azure-devops-rest-api azure-rest-api


    【解决方案1】:

    您似乎同时以两种不同的方式进行身份验证:

    • GetTfsCredentials-方法中设置 Windows 身份验证(NTLM 或 Kerberos)
    • 通过添加 client.DefaultRequestHeaders.Authorization 您尝试设置基本身份验证

    您的 TFS 表明(参见WWW-Authenticate Header)它支持承载、协商和 NTLM;但不是基本的。

    我会尝试:

    1. 删除client.DefaultRequestHeaders.Authorizationcredentialscredentials2。这应该删除基本身份验证
    2. 删除UseDefaultCredentials = true,因为您在下一行设置了显式凭据。 UseDefaultCredentials 告诉 HttpClientHandler 使用正在运行的进程的凭据访问 TFS,这可能是您在本地执行时的帐户和在服务器上执行时的服务帐户。
      如果没有此行,则应使用指定的 NetworkCredential 访问 TFS。

    【讨论】:

    • 这似乎有效,但是现在我收到另一个错误:NotFound,我直接在浏览器中尝试了裸 URL,它确实返回了响应。不知道为什么通过 API 我收到 NotFound 错误。
    • http://www.{orgname}/tfs/{DEPT}/{projectName}/_apis/wit/wiql/fd32daa7-ecdb-41f7-aa36-6736dfbbb792 这是格式 - 可以在浏览器中使用,但不能通过 API。
    • 没关系,这是权限问题,分配后能够修复。谢谢。
    猜你喜欢
    • 2020-12-23
    • 2017-10-24
    • 2017-01-15
    • 2019-02-01
    • 2014-04-03
    • 2018-10-17
    • 2019-05-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多