首页 新闻 会员 周边 捐助

c# httpclient模拟登录总是提示验证码错误

0
悬赏园豆:60 [已解决问题] 解决于 2014-12-19 09:09

 下面 是获取验证码图片的方法

 public static CookieContainer cookies = new CookieContainer();

public static string doGetImg(string Url)
{
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url.ToString());
request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
request.Headers.Add(HttpRequestHeader.AcceptLanguage, "zh-CN");
request.Accept = "text/html, application/xhtml+xml,*/*";
request.KeepAlive = true;

request.UserAgent = "User-Agent Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)";
request.Method = "get";
request.ContentType = "application/x-www-form-urlencoded";
request.AllowAutoRedirect = true;
request.Credentials = CredentialCache.DefaultCredentials;
request.Host = "www.luck.net";
request.CookieContainer = new CookieContainer(); //暂存到新实例
HttpWebResponse response = (HttpWebResponse)request.GetResponse();


string kes = response.ContentEncoding.ToLower();
Stream responseStream = null;
MemoryStream ms = null;
if (response.ContentEncoding.ToLower() == "gzip")
{
responseStream = new GZipStream(response.GetResponseStream(), CompressionMode.Decompress);
using (var stream = responseStream)
{
Byte[] buffer = new Byte[4096];
int offset = 0, actuallyRead = 0;
do
{
actuallyRead = stream.Read(buffer, offset, buffer.Length - offset);
offset += actuallyRead;
}
while (actuallyRead > 0);
ms = new MemoryStream(buffer);
}

}
cookies = request.CookieContainer; //保存cookies
response.Close();
// cookiesstr = request.CookieContainer.GetCookieHeader(request.RequestUri); //把cookies转换成字符串
System.Drawing.Image img = Bitmap.FromStream(ms);
string fn = System.IO.Path.Combine("/Resource/UploadFile/", Guid.NewGuid().ToString() + ".jpg");
string address = HttpContext.Current.Server.MapPath(fn);
img.Save(address, ImageFormat.Jpeg);
return fn;
}
catch
{
return null;
}
}

 

这个是模拟提交的方法

public static void PostLogin(string loginUrl, string account, string password, string code)
{
HttpWebRequest request = null;
HttpWebResponse response = null;
try
{
string postdata = "kcUserName=" + account + "&kc_j_captcha_response=" + code.ToLower() + "&kcPassword=" + password;//模拟请求数据,数据样式可以用FireBug插件得到。
request = (HttpWebRequest)WebRequest.Create(loginUrl);//实例化web访问类
request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
request.Headers.Add(HttpRequestHeader.AcceptLanguage, "zh-CN");
request.Accept = "text/html, application/xhtml+xml,*/*";
request.KeepAlive = true;
request.Referer = "http://www.luck.net/kcLogin.action";
request.Headers.Add(HttpRequestHeader.CacheControl, "no-cache");
request.UserAgent = "User-Agent Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0";
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.AllowAutoRedirect = true;
request.Credentials = CredentialCache.DefaultCredentials;

request.Host = "www.luck.net";
// request.AllowAutoRedirect = false; // 不用需自动跳转
//必须设置CookieContainer存储请求返回的Cookies
if (cookies != null)
{
request.CookieContainer = cookies;
}
else
{
request.CookieContainer = new CookieContainer();
cookies = request.CookieContainer;
}
//提交请求
byte[] postdatabytes = Encoding.UTF8.GetBytes(postdata);
request.ContentLength = postdatabytes.Length;
Stream stream;
stream = request.GetRequestStream();
//设置POST 数据
stream.Write(postdatabytes, 0, postdatabytes.Length);
stream.Close();
//接收响应
response = (HttpWebResponse)request.GetResponse();
string sdp = response.ContentEncoding.ToLower();
//保存返回cookie
// bCookie.upcookie(response.Cookies);
response.Cookies =request.CookieContainer.GetCookies(request.RequestUri);
CookieCollection cook = response.Cookies;
string strcrook = request.CookieContainer.GetCookieHeader(request.RequestUri);
CookiesString = strcrook;
Stream responseStream = null;
if (response.ContentEncoding.ToLower() == "gzip")
{
responseStream = new System.IO.Compression.GZipStream(response.GetResponseStream(), System.IO.Compression.CompressionMode.Decompress);
}
else if (response.ContentEncoding.ToLower() == "deflate")
{
responseStream = new System.IO.Compression.DeflateStream(response.GetResponseStream(), System.IO.Compression.CompressionMode.Decompress);
}
else
{
responseStream = response.GetResponseStream();
}
StreamReader sr = new StreamReader(responseStream, Encoding.UTF8);
string content = sr.ReadToEnd();
sr.Close();
request.Abort();
response.Close();
if (content.Contains("验证码错误"))
{
ShowMsgHelper.Alert_Error("验证码错误");
return;
}

}
catch (Exception ex)
{

}
}

 

这个是登录网站http://www.luckyair.net/kcLogin.action

尼哈的主页 尼哈 | 初学一级 | 园豆:38
提问于:2014-12-16 13:17
< >
分享
最佳答案
0

http 是个无状态的协议,

简单说就是你提交数据时,跟你取验证码图片的请求不是同一个sessionId,所以服务器认为你根本就跟拿图片的不是同一个人

所以服务器上存放的图片对应的验证码不是同一个,

解决办法就是保证你们是同一个sessionId就可以了

而sessionId又是用cookie来生成实现的,所以保证你2个请求是用的同一个cookie 就可以了

如何保证是同一个cookie呢,你用一个request发请求,获取图片,然后接着用这个request 去提交数据就可以了

 

但这里需要注意一下,你提交的数据格式(post的数据),必须是符合服务器的能识别的格式的,写错格式的话,服务器也是无法正常接收的,一样过不了。

收获园豆:40
装深沉的猫 | 菜鸟二级 |园豆:442 | 2014-12-18 17:41
其他回答(5)
0

那证明这个api需要验证码登录,而你又没有提供。

幻天芒 | 园豆:37205 (高人七级) | 2014-12-16 13:42

验证码我已经获取到,输入了

支持(0) 反对(0) 尼哈 | 园豆:38 (初学一级) | 2014-12-16 13:46

@尼哈: 必须要是同一个session。怕你二次提交的时候,后台的验证码已经变化了。

支持(0) 反对(0) 幻天芒 | 园豆:37205 (高人七级) | 2014-12-16 14:42
0

验证码你怎么获取的?有的网站验证码只要获取一次,再提交就没用了。

爱编程的大叔 | 园豆:30844 (高人七级) | 2014-12-16 14:27

我是根据网站获取验证码的网址获取的的验证码图片,然后保存在本地,在读取验证码图片,登录

支持(0) 反对(0) 尼哈 | 园豆:38 (初学一级) | 2014-12-16 14:29

@尼哈: 这样就是两次了。

支持(0) 反对(0) 爱编程的大叔 | 园豆:30844 (高人七级) | 2014-12-16 14:46

@爱编程的大叔: 恩,这个为什么是两次

支持(0) 反对(0) 尼哈 | 园豆:38 (初学一级) | 2014-12-16 14:48

@尼哈: 这样是两次没错,但服务器端的验证码应该还没变化,

  第一次:获取登陆网页

  第二次:根据url获取验证码图片

这个操作步骤跟浏览器是一样一样的

支持(1) 反对(0) 菜鸟范 | 园豆:61 (初学一级) | 2014-12-18 17:42
0

1.保证请求的在一个cookie内

2.保证请求验证码与请求数据是一个sessionId

3.仔细检查浏览器中登录与httpwebrequest,看看有没有哪里写错了

你这个方法写的太乱了,先把webrequest抽象成一个浏览器,再写代码

收获园豆:20
SpringRen | 园豆:412 (菜鸟二级) | 2014-12-16 20:05
0

话说,你验证码获取完之后怎么识别出字符来的?

菜鸟范 | 园豆:61 (初学一级) | 2014-12-18 17:42
0

请问怎么验证码是怎么识别出来的?

菜鸟004 | 园豆:202 (菜鸟二级) | 2016-09-30 08:34
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册