我正在尝试让我的应用程序在外部网站上执行登录操作。我使用以下代码:
Dim enc As Encoding = Encoding.UTF8
Dim Data As Byte() = Nothing
Dim req As HttpWebRequest
req = CType(Net.WebRequest.Create(URL), Net.HttpWebRequest)
req.Method = method
req.CookieContainer = CookieJar
req.AllowAutoRedirect = False
If method = "POST" Then
req.ContentType = "application/x-www-form-urlencoded"
Data = enc.GetBytes(PostData)
If Data.Length > 0 Then
req.ContentLength = Data.Length
Dim newStream As Stream = req.GetRequestStream()
newStream.Write(Data, 0, Data.Length)
newStream.Flush()
newStream.Close()
End If
End If
Dim Response As Net.HttpWebResponse = CType(req.GetResponse(), Net.HttpWebResponse)
Dim ResponseStream As IO.StreamReader = New IO.StreamReader(Response.GetResponseStream(), enc)
Dim Html As String = ResponseStream.ReadToEnd()
Response.Close()
ResponseStream.Close()
Return Html
什么有效:
- 响应具有所有正确的“Set-Cookie” header
- 容器保存所有正确的 Cookie(总共 5 个)
什么不起作用:
- 容器正确检索所有 cookie。但并非所有 cookie 都会与下一个请求一起发送。 4 个 cookie 设置正确,但最重要的一个未发送。
未发送的cookie是这个:
Set-Cookie: mpSecurity="ODc2NzM2ODoxMzUODViNTg5OWM1NTNlOWMwYmMxYjUxNWZjYzJjOGQyZGU4MTc2M2M=";Version=1;Path=/;Domain=.xxxxx.nl;Discard
此 cookie 与正确发送的 cookie 之间的唯一区别是,此 cookie 中包含“Version=1”和“Discard”...
有人知道为什么除了上面的 cookie 之外,所有检索到的 cookie 都会被发送吗?
如有任何帮助,我们将不胜感激!
最佳答案
这是 CookieContainer 中常见的已知错误:Link Here 适用于 4.0 以下的 .Net 版本
注意 Set-Cookie header 的域:
Cookie # 1 -> Set-Cookie: mpSecurity="ODc2NzM2ODoxMzUODViNTg5OWM1NTNlOWMwYmMxYjUxNWZjYzJjOGQyZGU4MTc2M2M=";Version=1;Path=/;Domain=marktplaats.nl;Discard
Cookie # 2 -> Set-Cookie: mpSecurity="ODc2NzM2ODoxMzUODViNTg5OWM1NTNlOWMwYmMxYjUxNWZjYzJjOGQyZGU4MTc2M2M=";Version=1;Path=/;Domain=.marktplaats.nl;Discard
当 URL 格式类似于 http://marktplaats.nl/...
时,会发送 Cookie #1
当 URL 格式类似于 http://www.marktplaats.nl/...
这就是问题
这是解决方案#1:(更好且简单的一个)
class DomainComparer : StringComparer
{
public override int Compare(string x, string y)
{
if (x == null || y == null)
{
return StringComparer.OrdinalIgnoreCase.Compare(x, y);
}
if (x.StartsWith("www.", StringComparison.OrdinalIgnoreCase))
{
x = x.Substring(4);
}
if (y.StartsWith("www.", StringComparison.OrdinalIgnoreCase))
{
y = y.Substring(4);
}
return StringComparer.OrdinalIgnoreCase.Compare(x, y);
}
public override bool Equals(string x, string y)
{
return Compare(x, y) == 0;
}
public override int GetHashCode(string obj)
{
if (obj.StartsWith("www.", StringComparison.OrdinalIgnoreCase))
{
obj = obj.Substring(4);
}
return StringComparer.OrdinalIgnoreCase.GetHashCode(obj);
}
}
/// <summary>
/// this is a hackfix for microsoft bug, where cookies are not shared between www.domain.com and domain.com
/// </summary>
/// <param name="cc"></param>
static void ImproveCookieContainer(ref CookieContainer cc)
{
Hashtable table = (Hashtable)cc.GetType().InvokeMember(
"m_domainTable",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Instance,
null, cc, new object[] { });
var comparerPreperty = table.GetType().GetField("_keycomparer",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Instance);
if (comparerPreperty != null)
{
comparerPreperty.SetValue(table, new DomainComparer());
}
}
解决方案 #1 的实现,每当您创建 CookieContainer 实例时,只需调用该方法一次
void main()
{
CookieContainer cookieJar = new CookieContainer();
ImproveCookieContainer(ref cookieJar);
// then use it with the WebRequest object
}
这里是解决方案#2:
- 不要使用 .Add(Cookie),仅使用 .Add(Uri, Cookie) 方法。
每次向容器添加 cookie 时调用 BugFix_CookieDomain 或 在您使用 .GetCookie 之前或在系统使用容器之前。
private void BugFix_CookieDomain(CookieContainer cookieContainer) { System.Type _ContainerType = typeof(CookieContainer); Hashtable table = (Hashtable)_ContainerType.InvokeMember("m_domainTable", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Instance, null, cookieContainer, new object[] { }); ArrayList keys = new ArrayList(table.Keys); foreach (string keyObj in keys) { string key = (keyObj as string); if (key[0] == '.') { string newKey = key.Remove(0, 1); table[newKey] = table[keyObj]; } } }
所有功劳都归功于 CallMeLaNN 的解决方案
关于.net - HttpWebRequest 未发送所有 cookie,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14523811/