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>
相关文章推荐
- AFNetworking 3.0迁移指南
- android httpclient基本用法
- HDU5461 Largest Point 贪心(2015acm沈阳网络赛)
- tcp三次握手
- linux0.99网络模块-传输层(TCP接收)
- META标签中的<http-equiv>属性值“content-Type”
- 计算机网络七层模型中对应的协议
- 自己动手写一个 iOS 网络请求库(五)——设置 SSL 钢钉
- HTTP Referer 二三事
- 网络访问受限
- python网络爬虫
- 神经网络之Hebb学习规则
- HTTP协议超级详解
- 在虚拟化环境下的网络
- tcp多客户端程序设计
- nginx-http-concat静态资源文件合并
- HDU 5451 Best Solver (2015年沈阳赛区网络赛B题)
- 在OC中关于URL和HTTP的理解
- 同步网络时间的 NTP 协议被发现存在8个漏洞
- 电脑常见网络为问题检测