在头部添加授权

33

我有如下代码:

...
AuthenticationHeaderValue authHeaders = new AuthenticationHeaderValue("OAuth2", Contract.AccessToken);
string result = await PostRequest.AuthenticatedGetData(fullUrl, null, authHeaders);
return result; 
...

public static async Task<string> AuthenticatedGetData(string url, FormUrlEncodedContent data, AuthenticationHeaderValue authValue)
{

    HttpClient client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authValue.Parameter);

    HttpResponseMessage response = await client.PostAsync(new Uri(url), data);

    response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response.EnsureSuccessStatusCode();
    string responseBody = await response.Content.ReadAsStringAsync();
    return responseBody;
}

使用 await part 的响应只是继续一个正在进行的循环,什么也不会发生。有任何想法我做错了什么吗?

实际问题是,我该如何发送以下标头:

Authorization: OAuth2 ACCESS_TOKEN

连接外部 Web API

5个回答

77

我曾为此苦恼。因为我实现了自定义认证方式,而Authorization头需要符合特定的标准才能通过验证,所以我一直收到“无效格式”的错误提示。但是通过以下方式添加Header却奏效了:

var http = new HttpClient();
http.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "key=XXX");

虽然这个标题看起来很奇怪,但它是Google云消息服务所需的Authorization头的格式,该服务将消息发送到Android设备。 - Parth Shah
我花了一个小时才搞定这个 :(。非常感谢你。 - Anupam Singh
有人在Windows 10上测试过这个吗?即使使用此绕过方法,它仍然失败。这真是让人恼火。 - Sinaesthetic
1
不知道为什么在Windows 10上会有问题,毕竟.NET代码是一样的吧? - John
这对我没有用。不得不求助于老实可靠的HttpWebRequest,它似乎可以正确地接受Google格式的标头。 - Exulted
对我来说运行得很好,谢谢!救了我的一命。 http.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", myVariableWithCustomAuthFormat); - eidylon

32

这一行

client.DefaultRequestHeaders.Authorization = 
           new AuthenticationHeaderValue(authValue.Parameter);

将生成此标题值

Authorization: ACCESS_TOKEN

其中ACCESS_TOKENauthValue.Parameter的值。您希望将传递的值分配给所需的标头。

client.DefaultRequestHeaders.Authorization = authValue;

将会产生

Authorization: OAuth2 ACCESS_TOKEN

我现在可以看到这个工作了。DefaultRequestHeaders已经按照你说的设置好了。我应该假设因为它没有工作,我没有通过正确的头信息发送请求吗?我瞥了一眼OAUTH文档,发现还有一些值需要发送...虽然我正在使用的API明确表示您“需要使用上述标头进行未来的API请求”。 - Jimmyt1988

14

在使用 GitHub 上的 JWT JsonWebToken 时,我遇到了一个类似的问题,即在尝试与请求一起使用 AuthenticationHeaderValue 时遇到了困难。我能够从 API 中获取到一个令牌,但是在其他 GET 和 POST 请求中使用它时遇到了麻烦。

var jwt = JsonWebToken.Encode(token, APISECRET, JwtHashAlgorithm.HS256);
var tk = GetTokenFromApi(); // basically returns an encrypted string.

手动使用 WebRequest:这很好地解决了问题。

request.ContentType = "application/json";
request.Method = "POST";
request.Headers.Set("Authorization", string.Format("Bearer {0}", tk));

当我们切换到 HttpClient 并使用 AuthenticationHeaderValue 时,无法弄清如何正确设置。查看请求字符串后,发现它已经为我添加了 "Authorization"。尝试了各种参数后,最终这个方法成功了。

 var authenticationHeaderValue = new AuthenticationHeaderValue("Bearer", tk);

3

在你的代码中,你正在做这个:

client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", $"{token}");

我认为以下内容在不使用字符串插值的情况下应该能够以相同的方式工作:
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

这是因为字符串插值只是生成一个包含标记的字符串!

2
也许对其他人有用。因为我花了很长时间来搜索这个。但是你也必须保存你的cookies,并在下一个请求中将其带上。首先,这就是我得到我的身份验证代码并在静态变量中保留我的cookies的方法(在第一次调用此方法时,我将token值设置为空)。
    public static CookieContainer CookieContainer;
    public static async Task<string> Post<TRequest>( TRequest requestBody, string path, string token = "")
    {
        var baseUrl = new Uri($"urlFromApi");
        CookieContainer = new CookieContainer();
        using (var handler = new HttpClientHandler() { CookieContainer = CookieContainer })
            using(var client = new HttpClient(handler){BaseAddress = baseUrl})
        {
            client.DefaultRequestHeaders.ConnectionClose = false;
            if (!string.IsNullOrWhiteSpace(token))
            {
                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", $"{token}");
            }
            ServicePointManager.FindServicePoint(client.BaseAddress).ConnectionLeaseTimeout = 60 * 1000; //1 minute            using (var content = new ByteArrayContent(GetByteData(requestBody)))
            using (var content = new ByteArrayContent(GetByteData(requestBody)))
            {
                content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                var response = await client.PostAsync(String.Empty, content);
                return await GetResponseContent(response);
            }
        }

    }

如果我对API进行任何请求,我都会包含cookie(令牌是第一个响应的结果)。以下是示例代码:

public static async Task Get(string path, string token = "")
{
    // 在此处添加代码以使用令牌进行请求
}

"Original Answer"的翻译是"最初的回答"。

        var baseUrl = $"https://innoviris-ai.collibra.com/rest/2.0{path}";
        using (var handler = new HttpClientHandler() { CookieContainer = CookieContainer })
        using (var client = new HttpClient(handler) {BaseAddress = new Uri(baseUrl)})
        {
            client.DefaultRequestHeaders.ConnectionClose = false;
            if (!string.IsNullOrWhiteSpace(token))
            {
                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", $"{token}");
            }
            ServicePointManager.FindServicePoint(client.BaseAddress).ConnectionLeaseTimeout = 60 * 1000; //1 minute     

            var response = await client.GetAsync(String.Empty);
            return await GetResponseContent(response);
        }
    }

${token}是多余的。它等同于string.Format("{0}", token),其中token已经是一个string类型`。 - Jonathan Gilbert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接