如何解析HttpWebResponse.Headers.Keys以获取返回的Set-Cookie会话ID

24

我试图创建一个带有ASP.NET网站的HttpWebRequest / HttpWebResponse会话,以便通过url参数解析HTML表单(我知道如何执行此操作),但我不知道如何解析和设置cookie,例如会话ID。 在Fiddler中,它显示ASP.NET会话ID通过Set-Cookie返回到URL路径的请求响应中,但是我如何提取此会话ID并将其设置为下一个HttpWebRequest的cookie?我知道Set-Cookie标头可以在HttpWebResponse.Headers.Keys中找到,但是否有直接解析它的方法?谢谢!

4个回答

58
.NET框架将为您管理Cookie。您不必担心从标头中解析Cookie信息或向请求添加Cookie标头。
使用CookieCookieContainer类来存储和发送会话ID,然后确保在每个请求中发送cookie。
以下示例显示如何执行此操作。CookieContainer 'cookieJar'可以在多个域和请求之间共享。一旦将其添加到请求对象中,当返回响应时,对它的引用也将添加到响应对象中。
CookieContainer cookieJar = new CookieContainer();

var request = (HttpWebRequest)HttpWebRequest.Create("http://www.google.com");
request.CookieContainer = cookieJar;

var response = request.GetResponse();

foreach (Cookie c in cookieJar.GetCookies(request.RequestUri))
{
    Console.WriteLine("Cookie['" + c.Name + "']: " + c.Value);
}

这段代码的输出结果将会是:

Cookie['PREF']: ID=59e9a22a8cac2435:TM=1246226400:LM=1246226400:S=tvWTnbBhK4N7Tlpu


+1 感谢您的帮助,我非常感激!我并不想手动解析HTTP头部 :) - jv42
这是一个意外的行为... 当CookieContainer未定义时,response.Cookies不应为空。 - Davi Fiamenghi
1
@DaviFiamenghi,这是已记录的行为。微软希望您拥有一个单一的cookie管理对象,以在Web请求/响应之间共享。如果您没有这样做,您将需要手动解析响应头中的cookies。 - Dan Herbert
@DanHerbert 非常好。但我仍然认为,如果在没有定义容器的情况下尝试访问响应的“Cookies”属性,则抛出InvalidOperationException会更直观。当我看到0个cookie时,我认为响应中没有0个cookie。这种行为就像尝试读取已处置的流或类似的东西...我相信,如果抛出解释性异常,它可以防止人们在SO上提问或自己滚动cookie解析逻辑。 - Davi Fiamenghi

8
丹·赫伯特的回答确实帮了我很多,非常感谢你的帮助。
我想分享一下我的用法-希望它能在某个时刻帮助到某个人。我的要求是我需要将第一个http post响应中的cookies发送回第二个http post请求。
1st:
CookieContainer cookieJar = new CookieContainer();
request.CookieContainer = cookieJar;
....

CookieCollection setCookies = cookieJar.GetCookies(request.RequestUri);

第二点:

CookieContainer cc = new CookieContainer();
cc.Add(setCookies);    
request.CookieContainer = cc;

5
我遇到了和亚马逊一样的问题。 我使用以下正则表达式:
string regexp = "(?<name>[^=]+)=(?<val>[^;]+)[^,]+,?";
MatchCollection myMatchCollection = Regex.Matches(cookiesStr, regexp);
foreach (Match myMatch in myMatchCollection)
{
    string cookieName = myMatch.Groups["name"].ToString();
    string cookieVal = myMatch.Groups["val"].ToString();
    Cookie cookie = new Cookie(cookieName, cookieVal);
    cookies.Add(cookie);
}
请注意,我只关心cookie的名称/值...祝好运! Elia

这正是我正在寻找的解决方案(WebBrowser对象仅提供cookie的字符串)。但是,您的代码无法编译。 - marknuzz

1

嗯,我可能错了,但最近我观察到从第一个响应中获取的Cookie不包括头部中传递的“set cookie”(例如一些会话ID...)在302(重定向)状态的情况下。

如果将自动跟随重定向设置为true,则会处理设置cookie,并且自动执行的后续请求将包括在第一次调用期间由设置cookie定义的那些cookie。

如果将自动跟随重定向设置为false,则第一个请求不会得到由设置cookie指定的cookie位置,我猜这也是我的问题:如果有人知道,那么随后在下一次请求中获得这些cookie的唯一方法是解析设置cookie吗?


我遇到了302重定向的问题,并设置AllowAutoRedirect = false。这给了我一个“此页面已移动”的响应,但然后我传递了cookies并重定向到我最初想要访问的页面。 - Daryl
1
根据RFC 6265规定,用户代理可以忽略包含100级状态代码的响应中的Set-Cookie标头,但必须处理其他响应中包含的Set-Cookie标头(包括400和500级状态代码的响应)。 - Snives

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接