您的位置:首页 > 理论基础 > 计算机网络

HttpClient 模拟登陆百度 2015.10.21 JAVA

2015-10-21 09:35 716 查看
最近研究了下httpclient,写了个模拟登陆百度的程序。觉得挺好玩的和大家分享一下。我使用的语言是java
我讲一下我的思路:


一:登陆的参数准备(chrome的开发人员工具)

1.cookie




2.这个是我们登陆百度最关键的一次请求



二.接下来我们要做的事就是获得某些关键参数

1.cookies 可以通过访问任意百度网站获得

2.token 访问

https://passport.baidu.com/v2/api/?getapi&class=login&tpl=mn&tangram=true

3.因为百度是通过rsa加密的,所以我们还要拿到公钥和签名(通过访问https://passport.baidu.com/v2/getpublickey)所有没有去获取公钥步骤的模拟登陆百度程序都是不可用的

4.验证码 验证码是通过访问https://passport.baidu.com/cgi-bin/genimage获取

ok ,关键参数的基本获取思路就是这样,下面看代码,代码比较简单 只有2个类 一个是rsa加密工具类 一个是登陆主程序

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.FileUtils;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.CookieStore;
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.BasicCookieStore;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import Utils.RSAUtil;

public class BaiDu {
public static void main(String[] args) {
new BaiDu().vmain();
}

HttpClient client;
Map<String, String> context = new HashMap<String, String>() {
public String put(String key, String value) {
System.out.println(key + ":" + value);
return super.put(key, value);
};
};
CookieStore cookieStore;
HttpGet get;
HttpPost post;

HttpResponse res;

public BaiDu() {
try {
cookieStore = new BasicCookieStore();
List<Header> headers = new ArrayList<Header>();
headers.add(new BasicHeader("user-agent",
"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/35.0"));
client = HttpClients.custom().setDefaultCookieStore(cookieStore)
.setDefaultHeaders(headers).build();
get = new HttpGet();
res = null;
get.setURI(new URI("http://pan.baidu.com
4000
/"));
client.execute(get);
getToken();
context.put("username", "用户名");
context.put("pass", "密码");
Encrypt();
login();
} catch (Exception e) {
System.out.println("init fail!");
e.printStackTrace();
}
}

/**
* @throws Exception
*/
public void Encrypt() throws Exception {
get = new HttpGet();
get.setURI(new URI("https://passport.baidu.com/v2/getpublickey?token="
+ context.get("token") + "&tpl=mn&apiver=v3&tt="
+ System.currentTimeMillis()));
res = client.execute(get);
String string = EntityUtils.toString(res.getEntity());
Matcher matcher = Pattern.compile(
"-----BEGIN PUBLIC KEY-----(.*)-----END PUBLIC KEY-----")
.matcher(string);
if (matcher.find()) {
String s = matcher.group(1);
context.put("pass", RSAUtil.encrypt(
s.replace("\\n", "").replace("\\/", "/"),
context.get("pass")));
}
Matcher matcher2 = Pattern.compile("\"key\":'(.+)'}$").matcher(string);
if (matcher2.find()) {
context.put("rsakey", matcher2.group(1));
}
}

private void errorhandle() throws Exception {
if (context.get("error") == null) {
System.out.println("登陆成功");
return;
}
switch (Integer.valueOf(context.get("error"))) {
case 257:
get.setURI(new URI("https://passport.baidu.com/cgi-bin/genimage?"
+ context.get("codeString")));
res = client.execute(get);
File file = new File("D:/baidu/" + context.get("username") + ".gif");
FileUtils.touch(file);
OutputStream os = new FileOutputStream(file);
res.getEntity().writeTo(os);
os.close();
volidate();
break;
case 0:
System.out.println("登陆成功");
break;
default:
break;
}
}

public String getToken() throws Exception {
get.setURI(new URI(
"https://passport.baidu.com/v2/api/?getapi&class=login&tpl=mn&tangram=true"));
res = client.execute(get);
BufferedReader br = new BufferedReader(new InputStreamReader(res
.getEntity().getContent()));
String line = null;
while ((line = br.readLine()) != null) {
if (line.contains("login_token")) {
String token = line.substring(line.indexOf("'") + 1,
line.lastIndexOf("'"));
context.put("token", token);
return context.get("token");
}
}
return null;
}

public void login() throws Exception {
List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>() {
@Override
public boolean add(BasicNameValuePair e) {
if (e.getValue() == null) {
e = new BasicNameValuePair(e.getName(), "");
}
return super.add(e);
}
};
params.add(new BasicNameValuePair("staticpage",
"http://www.baidu.com/cache/user/html/jump.html"));
params.add(new BasicNameValuePair("charset", "utf-8"));
params.add(new BasicNameValuePair("apiver", "v3"));
params.add(new BasicNameValuePair("token", context.get("token")));
params.add(new BasicNameValuePair("tpl", "mn"));
params.add(new BasicNameValuePair("tt", System.currentTimeMillis() + ""));
params.add(new BasicNameValuePair("safeflg", String.valueOf(0)));
params.add(new BasicNameValuePair("u", "http://pan.baidu.com/"));
params.add(new BasicNameValuePair("detect", "1"));
params.add(new BasicNameValuePair("gid", ""));
params.add(new BasicNameValuePair("quick_user", "0"));
params.add(new BasicNameValuePair("logintype", "basicLogin"));
params.add(new BasicNameValuePair("logLoginType", "pc_loginBasic"));
params.add(new BasicNameValuePair("idc", ""));
params.add(new BasicNameValuePair("loginmerge", "true"));
params.add(new BasicNameValuePair("rsakey", context.get("rsakey")));
params.add(new BasicNameValuePair("username", context.get("username")));
params.add(new BasicNameValuePair("password", context.get("pass")));
params.add(new BasicNameValuePair("isPhone", "false"));
params.add(new BasicNameValuePair("loginType", "1"));
params.add(new BasicNameValuePair("index", "0"));
params.add(new BasicNameValuePair("verifycode", context
.get("verifycode")));
params.add(new BasicNameValuePair("codestring", context
.get("codestring")));
params.add(new BasicNameValuePair("mem_pass", "on"));
params.add(new BasicNameValuePair("callback",
"parent.bdPass.api.login._postCallback"));
params.add(new BasicNameValuePair("crypttype", "12"));
post = new HttpPost();
post.setURI(new URI("https://passport.baidu.com/v2/api/?login"));
post.setEntity(new UrlEncodedFormEntity(params, "utf-8"));
res = client.execute(post);
String string = EntityUtils.toString(res.getEntity());
Matcher matcher = Pattern.compile("err_no=(\\d+)&").matcher(string);
if (matcher.find()) {
context.put("error", matcher.group(1));
} else {
matcher = Pattern.compile("error=(\\d+)'").matcher(string);
if (matcher.find()) {
context.put("error", matcher.group(1));
}
}
Matcher codem = Pattern.compile("code[sS]tring=(\\w+)&")
.matcher(string);
if (codem.find()) {
context.put("codeString", codem.group(1));
}
System.out.println(string);
errorhandle();
}

public void vmain() {
}

private void volidate() throws Exception {
System.out.println("请输入验证码:");
context.put("verifycode", new Scanner(System.in).next());
get.setURI(new URI("https://passport.baidu.com/v2/?checkvcode&token="
+ context.get("token") + "&tpl=mn&apiver=v3&tt="
+ System.currentTimeMillis() + "&verifycode="
+ context.get("verifycode") + "&codestring="
+ context.get("codeString")));
res = client.execute(get);
Matcher m = Pattern.compile("no\": \"(\\d+)\"").matcher(
EntityUtils.toString(res.getEntity()));
if (m.find()) {
switch (Integer.valueOf(m.group(1))) {
case 500002:
System.out.println("验证码错误");
break;
case 0:
System.out.println("验证成功");
login();
break;
default:
break;
}
}
}
}


package Utils;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
* RSA算法,实现数据的加密解密。
*
* @author ShaoJiang
*
*/
public class RSAUtil {

private static Cipher cipher;

static {
try {
cipher = Cipher.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
}

/**
* 生成密钥对
*
* @param filePath
*            生成密钥的路径
* @return
*/
public static Map<String, String> generateKeyPair(String filePath) {
try {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
// 密钥位数
keyPairGen.initialize(1024);
// 密钥对
KeyPair keyPair = keyPairGen.generateKeyPair();
// 公钥
PublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
// 私钥
PrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
// 得到公钥字符串
String publicKeyString = getKeyString(publicKey);
// 得到私钥字符串
String privateKeyString = getKeyString(privateKey);
// 将密钥对写入到文件
FileWriter pubfw = new FileWriter(filePath + "/publicKey.keystore");
FileWriter prifw = new FileWriter(filePath + "/privateKey.keystore");
BufferedWriter pubbw = new BufferedWriter(pubfw);
BufferedWriter pribw = new BufferedWriter(prifw);
pubbw.write(publicKeyString);
pribw.write(privateKeyString);
pubbw.flush();
pubbw.close();
pubfw.close();
pribw.flush();
pribw.close();
prifw.close();
// 将生成的密钥对返回
Map<String, String> map = new HashMap<String, String>();
map.put("publicKey", publicKeyString);
map.put("privateKey", privateKeyString);
return map;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

/**
* 得到公钥
*
* @param key
*            密钥字符串(经过base64编码)
* @throws Exception
*/
public static PublicKey getPublicKey(String key) throws Exception {
byte[] keyBytes;
keyBytes = (new BASE64Decoder()).decodeBuffer(key);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}

/**
* 得到私钥
*
* @param key
*            密钥字符串(经过base64编码)
* @throws Exception
*/
public static PrivateKey getPrivateKey(String key) throws Exception {
byte[] keyBytes;
keyBytes = (new BASE64Decoder()).decodeBuffer(key);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}

/**
* 得到密钥字符串(经过base64编码)
*
* @return
*/
public static String getKeyString(Key key) throws Exception {
byte[] keyBytes = key.getEncoded();
String s = (new BASE64Encoder()).encode(keyBytes);
return s;
}

/**
* 使用公钥对明文进行加密,返回BASE64编码的字符串
*
* @param publicKey
* @param plainText
* @return
*/
public static String encrypt(PublicKey publicKey, String plainText) {
try {
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] enBytes = cipher.doFinal(plainText.getBytes());
return (new BASE64Encoder()).encode(enBytes);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}

/**
* 使用keystore对明文进行加密
*
* @param publicKeystore
*            公钥文件路径
* @param plainText
*            明文
* @return
*/
public static String encrypt(String publicKeyString, String plainText) {
try {
// FileReader fr = new FileReader(publicKeystore);
// BufferedReader br = new BufferedReader(fr);
// String publicKeyString = "";
// String str;
// while ((str = br.readLine()) != null) {
// publicKeyString += str;
// }
// br.close();
// fr.close();
cipher.init(Cipher.ENCRYPT_MODE, getPublicKey(publicKeyString));
byte[] enBytes = cipher.doFinal(plainText.getBytes());
return (new BASE64Encoder()).encode(enBytes);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

/**
* 使用私钥对明文密文进行解密
*
* @param privateKey
* @param enStr
* @return
*/
public static String decrypt(PrivateKey privateKey, String enStr) {
try {
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] deBytes = cipher.doFinal((new BASE64Decoder())
.decodeBuffer(enStr));
return new String(deBytes);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}

/**
* 使用keystore对密文进行解密
*
* @param privateKeystore
*            私钥路径
* @param enStr
*            密文
* @return
*/
public static String decrypt(String privateKeystore, String enStr) {
try {
FileReader fr = new FileReader(privateKeystore);
BufferedReader br = new BufferedReader(fr);
String privateKeyString = "";
String str;
while ((str = br.readLine()) != null) {
privateKeyString += str;
}
br.close();
fr.close();
cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(privateKeyString));
byte[] deBytes = cipher.doFinal((new BASE64Decoder())
.decodeBuffer(enStr));
return new String(deBytes);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

}


我所使用的jar包

<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.7.3</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>1.10</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>fluent-hc</artifactId>
<version>4.3</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.3</version>
</dependency>
<dependency>
<groupId>org.htmlparser</groupId>
<artifactId>htmlparser</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>net.sourceforge.javaocr</groupId>
<artifactId>javaocr-core</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.6</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
<version>1.46</version>
</dependency>
</dependencies>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: