Azure DevOps API 调用 returns 401

Azure DevOps API call returns 401

我正在 .NET 6 中构建一个服务以与 Azure DevOps API 交互,但我在单一方法上不断收到 401 Unauthorized 响应。当我通过 Powershell 运行 时,我的个人访问令牌确实有效。我的 EncodeToken 方法似乎有效。关于为什么会爆炸的任何想法?

public class ADOService
    {
        private readonly HttpClient _httpClient;
        private readonly IConfiguration _config;
        private readonly string _token;
        private readonly string _rootUrl;
        private readonly string _project;

        public ADOService(IConfiguration configuration)
        {
            _config = configuration;
            _httpClient = new HttpClient();

            _token = _config.GetSection("AzureDevOpsApiSettings").GetValue<string>("ADOPersonalAccessToken");
            _rootUrl = _config.GetSection("AzureDevOpsApiSettings").GetValue<string>("ADORootUrl");
            _project = _config.GetSection("AzureDevOpsApiSettings").GetValue<string>("Project");

            if (string.IsNullOrEmpty(_token) || string.IsNullOrEmpty(_rootUrl) || string.IsNullOrEmpty(_project))
            {
                throw new Exception("ADO Service is not properly configured");
            }
        }

        public async Task<ExpandoObject> GetWorkItems()
        {
            SetHttpHeaders();
            HttpResponseMessage response = await _httpClient.GetAsync($"{_project}/_apis/wit/workitemsbatch?api-version=6.0");

            if (!response.IsSuccessStatusCode)
            {
                throw new ApplicationException("failed");
            }
            else
            {
                var content = await response.Content.ReadAsStringAsync();
                var workItems = JsonSerializer.Deserialize<ExpandoObject>(content);
                return workItems;
            }
        }

        private string EncodeToken(string token)
        {
            if (string.IsNullOrEmpty(token)) throw new ArgumentNullException("token");
            var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(token);
            return Convert.ToBase64String(plainTextBytes);
        }

        private void SetHttpHeaders()
        {
            _httpClient.BaseAddress = new Uri(_rootUrl);
            _httpClient.DefaultRequestHeaders.Accept.Clear();
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", EncodeToken(_token));
            _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        }
    }

您的 PAT 似乎未转换为有效的 Base64 字符串。

您可以参考示例 here 更改您的代码以将 PAT 转换为 Base64 字符串并将其添加到请求中 header.

public static async void GetProjects()
{
    try
    {
        var personalaccesstoken = "PAT_FROM_WEBSITE";

        using (HttpClient client = new HttpClient())
        {
            client.DefaultRequestHeaders.Accept.Add(
                new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
                Convert.ToBase64String(
                    System.Text.ASCIIEncoding.ASCII.GetBytes(
                        string.Format("{0}:{1}", "", personalaccesstoken))));

            using (HttpResponseMessage response = await client.GetAsync(
                        "https://dev.azure.com/{organization}/_apis/projects"))
            {
                response.EnsureSuccessStatusCode();
                string responseBody = await response.Content.ReadAsStringAsync();
                Console.WriteLine(responseBody);
            }
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }
}