WCF 数据服务错误 - 302 已在与 HTTPS 相关的 SaveChanges() 上移动负载均衡器?
问题:DataServiceContext.SaveChanges() 失败并出现“302 - 已移动”响应。
背景/可疑原因:负载均衡器! - 我们最近更改了基础设施,以便我们的 Web 服务器现在位于负载平衡器后面,该负载平衡器也处理 ssl。客户端将服务寻址为 HTTPS,但 IIS 最终处理 HTTP 请求,因为 SSL 是由负载均衡器完成的(我相信大多数人都熟悉这种类型的设置)。不管怎样,我们最终得到的是一个包含使用 HTTP 而不是 HTTPS 的 URI 的提要。 (请参阅下面的 GET 请求/响应,响应中使用 http 而不是 httpS)。这种行为非常奇怪,因为当我调用 saveChanges() 时,它会发送一个 MERGE(如预期),然后我返回 302:
HTTP/1.1 302 Object moved
Location: https://some.domain.org/CMSProfileService/ProfileDataService.svc/Mails(guid'80fef993-a4b5-4343-a908-28c2c6517a81')
Connection: close
但 WCF 不断使用 HTTP 一遍又一遍地尝试 MERGE(大约 50 次),然后最终抛出异常消息“处理此请求时发生错误。”,内部异常消息为“找到”。:)
当我直接指向服务器(绕过负载均衡器和 ssl)时,一切正常。当 SSL 直接在 IIS 中注册时,一切都正常。
一定有一些我找不到的配置设置/属性。 the-net-linq-providers-translation-to-odata-uri-format/6993670#6993670">类似问题的答案让我有点害怕。
这是来自 fiddler 的原始 GET 请求
GET https://some.domain.org/CMSProfileService2/ProfileDataService.svc/Mails()?$filter=Status%20eq%20'Queued'&$orderby=Timestamp&$expand=Attachments HTTP/1.1
User-Agent: Microsoft ADO.NET Data Services
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 2.0;NetFx
UserName:
Accept: application/atom+xml,application/xml
Accept-Charset: UTF-8
Host: some.domain.org
Connection: Keep-Alive
这是原始响应(经过修剪):
HTTP/1.1 200 OK
Set-Cookie: ARPT=RPZVOOS192.168.94.118CKOUM; path=/
Cache-Control: no-cache
Content-Length: 45849
Content-Type: application/atom+xml;charset=utf-8
Server: Microsoft-IIS/7.5
DataServiceVersion: 1.0;
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Mon, 22 Aug 2011 14:56:46 GMT
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<feed xml:base="http://some.domain.org/CMSPRofileService2/ProfileDataService.svc/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
<title type="text">Mails</title>
<id>http://some.domain.org/CMSProfileService2/ProfileDataService.svc/Mails</id>
<updated>2011-08-22T14:56:47Z</updated>
<link rel="self" title="Mails" href="Mails" />
<entry>
<id>http://some.domain.org/CMSPRofileService2/ProfileDataService.svc/Mails(guid'c7edb158-7a61-4fca-a40e-7f4a3a0b2bbd')</id>
<title type="text"></title>
<updated>2011-08-22T14:56:47Z</updated>
<author>
<name />
</author>
<link rel="edit" title="Mail" href="Mails(guid'c7edb158-7a61-4fca-a40e-7f4a3a0b2bbd')" />
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Attachments" type="application/atom+xml;type=feed" title="Attachments" href="Mails(guid'c7edb158-7a61-4fca-a40e-7f4a3a0b2bbd')/Attachments">
<m:inline>
<feed>
<title type="text">Attachments</title>
<id>http://some.domain.org/CMSPRofileService2/ProfileDataService.svc/Mails(guid'c7edb158-7a61-4fca-a40e-7f4a3a0b2bbd')/Attachments</id>
<updated>2011-08-22T14:56:47Z</updated>
<author>
<name />
</author>
<link rel="self" title="Attachments" href="Mails(guid'c7edb158-7a61-4fca-a40e-7f4a3a0b2bbd')/Attachments" />
</feed>
</m:inline>
</link>
<category term="XXX.YYY.Profile.Repository.Mail" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:MailId m:type="Edm.Guid">c7edb158-7a61-4fca-a40e-7f4a3a0b2bbd</d:MailId>
<d:Timestamp m:type="Edm.DateTime">2011-07-28T12:51:37.69</d:Timestamp>
<d:ApplicationCode>EREF</d:ApplicationCode>
<d:Status>Queued</d:Status
.
.
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这里的问题很可能是 self/links 编辑链接是 HTTP,而不是 HTTPS,因此客户端无法使用这些链接访问数据。 Per Vitek 的 可怕的答案。
不幸的是服务器不知道它在哪里。
我可以想到几个选项(它们都不是特别好):
AbsoluteServiceUri
属性告诉 Data Services 其根目录是 https://...。这样,数据服务应该生成适当的 URL-亚历克斯
The problem here is likely that the self/links edit links are HTTP, not HTTPS, so the client can't use the links to access the data. Per Vitek's scary answer.
The unfortunate thing is the server doesn't know where it is.
I can think of a couple of options (neither of them particularly nice):
AbsoluteServiceUri
property. That way Data Services should produce appropriate URLS-Alex
终于解决了这个讨厌的问题。实际上有两个问题。
问题 1:在负载均衡器后面的 IIS 中托管的 WCF 数据服务使用 https 创建带有 http URI 而不是 https 的源。这是可以理解的,也是我对这个问题的第一个猜测。通过大量挖掘,我发现了 这篇文章提供了一个非常直接的解决方案。
在我的服务的构造函数中,我连接到处理请求事件
在事件处理程序中,我使用提到的文章并进行了一些调整,基本上从 clientExpectsUri 获取主机、方案和端口,并将它们应用到请求 Uri。我还只是寻找一个名为“X-Client-Expects-RootUri”的自定义标头,防火墙外部的客户端如果需要有效的源,则需要发送该标头。
我实际上想要一些关于此设计的反馈,因为我基本上是要求客户告诉我如何通过自定义标头返回 URI。我将来会考虑修改负载均衡器以自动添加这些标头。
问题 #2:未针对 MERGE 和其他非 RFC http 方法配置负载均衡器。这个问题的解决方案很简单,只需设置 usePostTunneling 设置为 true。如果有人有为 cisco 11503 启用非 RFC http 方法的脚本,我很乐意拥有它们。 ;-)
Finally solved this nasty issue. There were actually two issues.
Issue #1: WCF Data Service hosted in IIS behind a load balancer with https creates feeds with http URIs rather than https. This is understandable and was my first guess into the issue. Through lots of digging I came across this article which provided a pretty straight forward solution.
In the constructor of my service I hook up to the processing request event
In the event handler, I use the article mentioned and made some tweaks that basically take the host, scheme and port from the clientExpectsUri and applies them to the request Uri. I also just look for a custom header that I called "X-Client-Expects-RootUri" that clients outside the firewall need to send if they want valid feeds.
I would actually like some feedback on this design, as I am basically asking the client to tell me how to return the URI via a custom header. I will be looking into modifying the load balancer in the future to add these headers automatically.
Issue #2: Load balancer was not configured for MERGE and other non-RFC http methods. The solution to this issue was simple, just set usePostTunneling to true on the DataServiceContext. If anyone has the scripts to enable non-RFC http methods for a cisco 11503, I'd love to have them. ;-)