使用HttpClient4.x实现模拟验证码登陆

先来简述一下没有验证码的网站登陆流程:

1、用户打开登陆页。这个动作完成的最关键的部分是,后台为这个浏览器新建了一个cookie,之后用户在这个浏览器的所有动作都将与这个Cookie密切相关。

2、用户输入用户名和密码(也许还有别的表单需要填写,视具体情况而定)。

3、用户点击“登陆”按钮。连同Cookie和表单一起提交到服务器,由服务器来处理后面的事情。

好,那么有验证码的情况又是怎么样的呢?

我先说一下我的错误示范:

我第一步是获取验证码(验证码的获取链接可以轻易获取,这里不再赘述。有了链接,下载验证码图片,然后读取图片上的数字,就可以获取验证码了。关于获取验证码的方法,可以关注我的另一篇文章,java读取图片上的数字(验证码))。

第二步,填充表单。

第三步,发送登陆请求。

我试了很多次,都是失败的,我不明白,已经保证了client的一致性,始终保持着cookie,为什么还是不行呢?

后来我明白了,验证码不是我把里边内容读取然后放到登陆请求表单里就行了的,这个验证码的内容是要和Cookie作关联的,所以在获取验证码之前,首先要创建Cookie,所以client首先要先get请求一下登陆地址(不过按我的理解,这个地址可以是该网站的任务一个地址,因为Cookie是服务器和浏览器之间的关联器件,不管是不是登陆页,都会在服务器生成一个对应的Cookie,所以首先访问的地址不一定就是登陆地址。)

这步完成之后,再重复一下我的错误示范,就应该可以了。

注意,要保持client不要变。

好,下面上代码:

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;


import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;


public class Client {
private String acctNo;
private String acctPass;
private HttpClient client = HttpClients.createDefault();//实例化httpclient


private Client(String acctNo, String acctPass) {
super();
this.acctNo = acctNo;
this.acctPass = acctPass;
}


private void login() {
HttpResponse response;
String rawHtml;


try {
HttpGet getLoginPage = new HttpGet("登陆页url");
//HttpGet getLoginPage = new HttpGet("表单action地址");
//首先访问一下这个服务器,随便哪个地址,建立Cookie
client.execute(getLoginPage);
//获取验证码
getVerifyingCode(client);


//设定post参数,和上图中的内容一致
ArrayList valuePairs = new ArrayList();
valuePairs.add(new BasicNameValuePair("acctNo", acctNo));
valuePairs.add(new BasicNameValuePair("acctPass", acctPass));
valuePairs.add(new BasicNameValuePair("checkCode", TestOne.getImgContent("verifyCode1.jpg")));


HttpPost post = new HttpPost("表单action地址");//构建post对象
post.setEntity(new UrlEncodedFormEntity(valuePairs));//捆绑参数
response = client.execute(post);//执行登陆行为
rawHtml = EntityUtils.toString(response.getEntity(), "utf-8");
System.out.println(rawHtml);
// 到这里已经登陆成功了,可以用下面的代码测试一下,会有惊喜的
HttpGet g = new HttpGet("任意一个必须登陆才能访问的地址");
HttpResponse r = client.execute(g);


System.out.println("--a----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------");
System.out.println(EntityUtils.toString(r.getEntity()));
System.out.println("--b----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------");
// 如果登陆失败,打印的内容应该是登陆页代码。不过我希望你看到的内容不是这样的
} catch (ClientProtocolException e) {
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
}
}


private void getVerifyingCode(HttpClient client) {
HttpGet getVerifyCode = new HttpGet("http://www.jspec.cn/includes/checkcode.jsp");//验证码get
FileOutputStream fileOutputStream = null;
HttpResponse response;
try {
response = client.execute(getVerifyCode);//获取验证码
/*验证码写入文件,当前工程的根目录,保存为verifyCode.jped*/
fileOutputStream = new FileOutputStream(new File("verifyCode1.jpg"));
response.getEntity().writeTo(fileOutputStream);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileOutputStream != null) {
fileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}


public static void main(String[] args) {
Client client = new Client("admin", "admin");
client.login();
}
}


你可能感兴趣的:(java)