授权标头在重定向时丢失 [英] Authorization header is lost on redirect

查看:628
本文介绍了授权标头在重定向时丢失的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是执行身份验证,生成Authorization标头并调用API的代码。

Below is the code that does authentication, generates the Authorization header, and calls the API.

不幸的是,我得到了 401 Unauthorized < API上的 GET 请求后,出现/ code>错误。

Unfortunately, I get a 401 Unauthorized error following the GET request on the API.

但是,当我在Fiddler中捕获流量并重播时,对API的调用成功,并且可以看到所需的 200 OK 状态代码。

However, when I capture the traffic in Fiddler and replay it, the call to the API is successful and I can see the desired 200 OK status code.

[Test]
public void RedirectTest()
{
    HttpResponseMessage response;
    var client = new HttpClient();
    using (var authString = new StringContent(@"{username: ""theUser"", password: ""password""}", Encoding.UTF8, "application/json"))
    {
        response = client.PostAsync("http://host/api/authenticate", authString).Result;
    }

    string result = response.Content.ReadAsStringAsync().Result;
    var authorization = JsonConvert.DeserializeObject<CustomAutorization>(result);
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authorization.Scheme, authorization.Token);
    client.DefaultRequestHeaders.Add("Accept", "application/vnd.host+json;version=1");

    response =
        client.GetAsync("http://host/api/getSomething").Result;
    Assert.True(response.StatusCode == HttpStatusCode.OK);
}

运行此代码时,授权标头丢失。

When I run this code the Authorization header is lost.

但是,在Fiddler中成功传递了标头。

However, in Fiddler that header is passed successfully.

知道我在做什么错吗?

推荐答案

出现此现象的原因是它是设计的

The reason you are experiencing this behavior is that it is by design.

大多数HTTP客户端(默认情况下)在重定向后会剥离授权标头。

Most HTTP clients (by default) strip out authorization headers when following a redirect.

一个原因是安全性。可以将客户端重定向到一个不受信任的第三方服务器,您不希望将该第三方服务器公开您的授权令牌。

One reason is security. The client could be redirected to an untrusted third party server, one that you would not want to disclose your authorization token to.

您可以做的是检测重定向是否具有

What you can do is detect that the redirect has occurred and reissue the request directly to the correct location.

您的API返回 401 Unauthorized 表示授权标头丢失(或不完整)。我将假设,如果请求中存在授权信息,但完全不正确(用户名/密码错误),则相同的API返回 403 Forbidden

Your API is returning 401 Unauthorized to indicate that the authorization header is missing (or incomplete). I will assume that the same API returns 403 Forbidden if the authorization information is present in the request but is simply incorrect (wrong username / password).

在这种情况下,您可以检测到重定向/缺少授权标头组合并重新发送请求。

If this is the case, you can detect the 'redirect / missing authorization header' combination and resend the request.

这是改写后的问题的代码,以执行以下操作:

Here is the code from the question rewritten to do this:

[Test]
public void RedirectTest()
{
    // These lines are not relevant to the problem, but are included for completeness.
    HttpResponseMessage response;
    var client = new HttpClient();
    using (var authString = new StringContent(@"{username: ""theUser"", password: ""password""}", Encoding.UTF8, "application/json"))
    {
        response = client.PostAsync("http://host/api/authenticate", authString).Result;
    }

    string result = response.Content.ReadAsStringAsync().Result;
    var authorization = JsonConvert.DeserializeObject<CustomAutorization>(result);

    // Relevant from this point on.
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authorization.Scheme, authorization.Token);
    client.DefaultRequestHeaders.Add("Accept", "application/vnd.host+json;version=1");

    var requestUri = new Uri("http://host/api/getSomething");
    response = client.GetAsync(requestUri).Result;

    if (response.StatusCode == HttpStatusCode.Unauthorized)
    {
        // Authorization header has been set, but the server reports that it is missing.
        // It was probably stripped out due to a redirect.

        var finalRequestUri = response.RequestMessage.RequestUri; // contains the final location after following the redirect.

        if (finalRequestUri != requestUri) // detect that a redirect actually did occur.
        {
            if (IsHostTrusted(finalRequestUri)) // check that we can trust the host we were redirected to.
            {
               response = client.GetAsync(finalRequestUri).Result; // Reissue the request. The DefaultRequestHeaders configured on the client will be used, so we don't have to set them again.
            }
        }
    }

    Assert.True(response.StatusCode == HttpStatusCode.OK);
}


private bool IsHostTrusted(Uri uri)
{
    // Do whatever checks you need to do here
    // to make sure that the host
    // is trusted and you are happy to send it
    // your authorization token.

    if (uri.Host == "host")
    {
        return true;
    }

    return false;
}






请注意,您可以保存 finalRequestUri 的值,并将其用于将来的请求,以避免重试中涉及的额外请求。但是,由于这是一个临时重定向,您可能应该每次都将请求发送到原始位置。


Note that you could save the value of finalRequestUri and use it for future requests to avoid the extra request involved in the retry. However as this is a temporary redirect you should probably issue the request to the original location each time.

这篇关于授权标头在重定向时丢失的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆