使用 WCF 的 Http 请求中缺少授权标头

Posted

技术标签:

【中文标题】使用 WCF 的 Http 请求中缺少授权标头【英文标题】:Authorization Header is missing in Http request using WCF 【发布时间】:2011-05-04 02:50:36 【问题描述】:

我正在使用 WCF 访问 Web 服务。使用 WSHttpBinding,安全模式设置为传输 (https),​​客户端凭据类型为基本。当我尝试使用代理访问服务时,收到 401 未经授权的异常。

这里是绑定

var binding = new WSHttpBinding()
        
            UseDefaultWebProxy = true,
            Security =
            
                Mode = SecurityMode.Transport,
                Transport =
                
                    ClientCredentialType = HttpClientCredentialType.Basic,
                ,
            
        ;

这里是服务调用

var client = new InternetClient(binding, new EndpointAddress("httpsurl"));

        client.ClientCredentials.UserName.UserName = "username";
        client.ClientCredentials.UserName.Password = "password";
        client.ProcessMessage("somevalue");

当使用 Http Analyzer 查看 Http 标头时 连接头

(请求行):CONNECT somehost.com:443 HTTP/1.1 主持人:somehost.com 代理连接:保持活动

帖子标题

(请求行):POST /Company/1.0 HTTP/1.1 内容类型:应用程序/soap+xml;字符集=utf-8 VsDebuggerCausalityData:uIDPo+voStemjalOv5LtRotFQ7UAAAAAUKLJpa755k6oRwto14BnuE2PDtYKxr9LhfqXFSOo8pEACQAA 主持人:somehost.com 内容长度:898 期望:100-继续 连接:保持活动状态

如果您看到标头授权标头丢失

现在我的问题是为什么 WCF 调用缺少授权标头?我错过了什么吗? .请询问您是否需要更多信息

【问题讨论】:

【参考方案1】:

这是一个常见的问题,但情况和你想的不一样。

事实证明,最初对于第一个请求,配置为使用 HTTP 基本身份验证的 WCF 客户端仍然会将没有必要的授权标头的请求发送到服务器。这是 WCF 客户端使用的 HttpWebRequest 类的默认行为。

通常,Web 服务服务器随后将向 WCF 客户端返回 HTTP 401 Unauthorized 响应,在此之后,WCF 客户端将重新发送带有 Authorization 标头的消息。这意味着在 HTTP 基本身份验证的正常情况下,将有一个相当无用的往返服务器。

这也解释了为什么嗅探消息中缺少标头。一些 Http 嗅探可能不会传递 401 响应,因此整个交换会变得一团糟。

通过手动将所需的授权标头注入每个请求,可以避免服务器往返和对 401 响应的依赖。参见例如how to manually inject Authorization header into WCF request

【讨论】:

什么?您确定这种行为吗?这对我来说似乎很荒谬。 是的,绝对确定 - 对其进行了广泛的测试并使用 Fiddler 研究了行为 - 推荐的解决方案按描述工作。我已经在生产中运行了这个。 是的,它也对我有用。但我还是很困惑。如果 WCF 开发人员没有从盒子中工作,而我们必须自定义该行为,那么他们创建了身份验证机制怎么办?! 救生员,我实现了一个有这个问题的服务,但是我从来没有接到一个往返电话。它只会调用一次而不添加标题。进行标头注入解决了它。 这解决了一个问题,我看到授权标头存在于小型有效负载但在较大(700K+)有效负载上,授权标头将被删除,并添加了以前不存在的保持活动标头.【参考方案2】:

作为对先前答案的轻微修改,为了支持 async / await 调用,您实际上可以创建一个新的 OperationContext 并在您喜欢的任何线程上传递它(只要它不是在并发线程之间共享的,因为它不是t 一个线程安全的对象)

var client = new MyClient();
client.ClientCredentials.UserName.UserName = "username"; 
client.ClientCredentials.UserName.Password = "password";
var httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Headers[HttpRequestHeader.Authorization] = "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(client.ClientCredentials.UserName.UserName + ":" + client.ClientCredentials.UserName.Password));

var context = new OperationContext(ormClient.InnerChannel);
using (new OperationContextScope(context))

    context.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
    return await client.SomeMethod();

【讨论】:

【参考方案3】:

请注意标题中的 Expect:100-continue。这就是往返的原因。

将其放入您的 web.config 并重试:

<system.net>
    <settings>
      <servicePointManager expect100Continue="false"/>
    </settings>
</system.net>

【讨论】:

这会删除 Expect: 100 Continue 标头,但不会添加 Authorization 标头【参考方案4】:

其实这个问题我错了。在运行 HTTP 分析器时,我确实看到了不同的行为。在 Http anaylzer 运行时,我的应用程序在收到 401 响应后崩溃。当 Http 分析器应用程序关闭时,上述代码按预期工作。

【讨论】:

以上是关于使用 WCF 的 Http 请求中缺少授权标头的主要内容,如果未能解决你的问题,请参考以下文章

PHP POST 请求中缺少授权标头

POST请求中缺少授权标头[重复]

NodeJS:使用 res.writeHead 的重定向缺少标头授权

如果通过 Zuul API 网关发送请求,则缺少授权标头

使用 JWT 缺少授权标头

当提供商因缺少授权标头而拒绝飞行前请求时,让客户端 CORS 工作