带空域的HttpWebRequest cookie

时间:2010-12-16 17:24:47

标签: httpwebrequest cookiecontainer

我有一个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是否使用空值来表示localhost,或者我是否需要为此问题找到另一个修复程序?

4 个答案:

答案 0 :(得分:8)

<强>声明:

如前面@feroze所述,将您的cookie域设置为localhost对您来说效果不佳。我假设您正在编写一个帮助程序,允许您将HTTP请求传递到外部域。请注意,这不是最佳做法,并且在很多情况下不需要(即jQuery has a lot of cool cross-domain support built-in,也请参阅新的CORS specification)。但有时候你可能会遇到这种情况(即外部资源只是XML,而且是在不支持CORS的服务器上)。

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

如果您尚未查看HTTP Cookie: Domain and Path on Wikipedia - 您需要知道的所有内容都在那里。

评估Cookie时, 客户端(“本地”请求者)和Web服务器(“外部”)会考虑域和路径应答器)。当客户端请求资源时,客户端仅发送cookie,其中这些cookie与URI的域(或更通用的parent domain)和Path(或更通用的父路径)匹配被要求。

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

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

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

我推荐给你的行动方案是,当你读到客户端的cookie时(我不是MVC人,但是在常规的ASP.NET中,这将是在Request.Cookies中),循环遍历它们(确保过滤掉你自己网站的合法cookie,特别是SessionId等 - 或者正确使用Path,这样他们就不会首先发送到这个页面),然后一次一个地添加到传出请求的cookie集合中,重写域名要成为“www.whatever.com”(根据您的示例 - 如果您动态执行此操作,请将URL加载到新的Uri()对象并使用.Host属性),然后将路径设置为“/” 。 - 这将为外部Web服务器的传出请求构建“Cookie”标头。

当该请求返回到您的服务器时,您需要检查它对新cookie的传入响应 - 这些cookie可以重新打包并以与前一段中所示相同类型的循环发送回客户端,除非你想要将Host重写为Request.Url.Host - 并且你想要将路径设置回“/”,除非你的passthru页面的路径是静态的(我猜它不是因为你正在使用MVC)然后你想将它设置为Request.Url.AbsolutePath。

快乐的编码!

修改 此外,您还需要设置传出请求的X-Forwarded-For标记,这样您所呼叫的网站就不会认为您的网络服务器是一个单独的客户端,而是垃圾邮件。“ p>

答案 1 :(得分:3)

一些背景

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

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

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

这就是 CookieContainer 中的Cookie需要拥有有效域名的原因。

相反,在服务器端上,Cookie是通过其他类型 CookieCollection 提供的,这是一个简单的Cookie列表,没有额外的逻辑。


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

答案 2 :(得分:2)

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

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

希望它有所帮助!

答案 3 :(得分:-1)

您正尝试将Cookie发送到localhost,对吗?

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

  1. 编辑您的主机文件并添加一行“127.0.0.1 myname.com”
  2. 使用myname.com进行测试 - 实际上是您的本地主机。
  3. 如果cookie属于的话,您的浏览器或应用程序将不会知道差异并将cookie发送到myname.com。

    详细信息:

    1. Windows上的Hosts文件位于 C:\ Windows \ System32 \ drivers \ etc \ hosts