22

我有一个 ASP.NET MVC 操作,它通过 HttpWebRequest 将 GET 请求发送到另一台服务器。我想在新请求中包含原始操作请求中的所有 cookie。原始请求中的某些 System.Web.HttpCookies 具有空域值(即“”),这显然不会导致任何问题。当我使用每个这些 cookie 的名称、值、路径和域创建 System.Net.Cookie 并将其添加到请求的 CookieContainer 时,我收到此错误:

“System.ArgumentException:参数“{0}”不能为空字符串。参数名称:cookie.Domain”

下面是一些会抛出相同错误的代码(当添加 cookie 时):

var request = (HttpWebRequest)WebRequest.Create("http://www.whatever.com");
request.Method = "GET";
request.CookieContainer = new CookieContainer();
request.CookieContainer.Add ( new Cookie ( "MyCookieName", "MyCookieValue", "/", "") );

编辑

我通过对域使用“localhost”来解决这个问题,而不是原始HttpCookie中的 null 或空字符串值。那么,为什么空域不适用于 CookieContainer? HttpCookie 是否使用空值来表示本地主机,还是我需要为这个问题找到另一个解决方案?

4

4 回答 4

9

免责声明:

正如@feroze 之前所说,将您的 cookie 域设置为 localhost 对您来说效果并不好。我假设您正在编写一个帮助程序,允许您将 HTTP 请求通过隧道传输到外部域。请注意,这不是最佳实践,并且在很多情况下不需要(即jQuery 内置了很多很酷的跨域支持,另请参阅新的CORS 规范)。但有时您可能会卡在这样做(即外部资源仅是 XML,并且位于不支持 CORS 的服务器上)。

关于 Cookie 域及其工作原理的背景信息:

如果您还没有查看过HTTP Cookie:Wikipedia 上的域和路径——您需要知道的几乎所有内容都在其中。

在评估 cookie 时,客户端(“本地”请求者)和 Web 服务器(“外部”响应者)都会考虑域和路径。当客户端请求资源时,客户端仅在这些 cookie 与请求的 URI 的域(或更通用的父域)和路径(或更通用的父路径)匹配的情况下发送 cookie。

Web 浏览器可以正确处理这个问题。例如,如果 Web 浏览器具有域“localhost”的 cookie,并且您正在请求“google.com”,则“localhost”域的这些 cookie 不会在请求中发送到“google.com”。-- 事实上,大多数现代浏览器不仅不会发送它们,它们还会在接收到的 Set-Cookie 响应标头中完全忽略它们(这些称为第三方 cookie——允许在您的网络浏览器是一个巨大的隐私/安全问题——不要这样做!)。

它也可以在另一个方向上工作——即使客户端不太可能在请求中包含第三方 cookie,如果包含,外部 Web 服务器应该忽略它(甚至一些用于正确域/路径的 cookie ,以防止臭名昭著的超级cookie问题。(即托管“example.com”的Web服务器应忽略属于其父域的cookie:“.com”,因为“.com”是“公共后缀”)) .

你应该做什么[如果你必须]:

我向您推荐的操作过程是,当您读取客户端的 cookie(我不是 MVC 人,但在常规 ASP.NET 中,这将在 Request.Cookies 中)时,循环浏览它们(确保过滤掉您自己网站的合法 cookie,尤其是 SessionId 等 - 或正确使用 Path,因此它们一开始就不会发送到此页面),然后一次将它们添加到传出请求的 cookie 集合中,将域重写为“ www.whatever.com”(根据您的示例——如果您正在动态执行此操作,请将 URL 加载到新的 Uri() 对象中并使用 .Host 属性),然后将路径设置为“/”。-- 这将为向外网络服务器的传出请求构建“Cookie”标头。

当该请求返回到您的服务器时,您需要检查新 cookie 的传入响应——这些 cookie 可以重新打包并以与我在前一段中说明的循环类型大致相同的循环发送回您的客户端,除了您'll想重写主机为request.url.host-除非您的传递页面的路径是静态的,否则您需要将路径设置回“/”使用 MVC)然后你想将它设置为 Request.Url.AbsolutePath 例如。

快乐编码!

编辑: 另外,您需要设置传出请求的X-Forwarded-For标记,以便您调用的网站不会认为您的 Web 服务器是一个向它们发送垃圾邮件的单个客户端。

于 2012-10-14T05:11:23.130 回答
5

不确定它是否能解决您的问题。但是要添加不带“域”属性的 cookie,您必须将 cookie 添加到标题中HttpRequestHeader.Cookie,如下所示。

request.Headers.Add(HttpRequestHeader.Cookie, "Your cookies...");

希望能帮助到你!

于 2016-08-24T05:09:12.177 回答
3

一些背景

这是因为 CookieContainer 是客户端容器,旨在跨多个 HttpWebRequest 重用。重用它提供了预期的 cookie 行为,即远程主机设置的 cookie 与针对同一主机的每个后续 HttpWebRequest 一起发回。

由于重用,CookieContainer 可能实际上包含来自多个请求和/或主机的 cookie。

因此,为了确定容器中的哪些 cookie 需要通过特定的 HttpWebRequest 发送到某个主机(域),CookieContainer 会检查 Domain 和 Path 属性。

这就是为什么CookieContainer中的 Cookie需要具有有效域的原因。

相反,在服务器端cookie 是通过不同的类型传递的,CookieCollection是一个简单的 cookie 列表,没有额外的逻辑。


具体来说,在您的情况下,在将 Cookie 从 CookieCollection 复制到 CookieContainer 时,您需要将每个 cookie 的 Domain 属性设置为您要将请求转发到的域,以便 HttpWebRequest 在发送请求时知道包含 cookie .

于 2013-05-28T22:56:21.050 回答
-1

您正在尝试将 cookie 发送到本地主机,对吗?

你为什么不做这样的事情,给你自己的机器一个真实的名字:

  1. 编辑您的主机文件并添加一行“127.0.0.1 myname.com”
  2. 使用 myname.com 进行测试 - 这实际上是您的本地主机。

您的浏览器或应用程序将不知道其中的差异并将 cookie 发送到 myname.com(如果这是 cookie 所在的位置)。

详细信息:

  1. Windows 上的 Hosts 文件位于C:\Windows\System32\drivers\etc\hosts
于 2011-02-23T10:04:29.000 回答