其实是想写Android的,但是调试太麻烦,就先写J2se再移植了。
要导入Jousp的项目或是源码。
main类(J2se的):
import javax.swing.JFrame;//框架
import javax.swing.JPanel;//面板
import javax.swing.JButton;//按钮
import javax.swing.JLabel;//标签
import javax.swing.JTextField;//文本框
import java.awt.Font;//字体
import java.awt.Color;//颜色
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionListener;//事件监听
import java.awt.event.ActionEvent;//事件处理
import java.net.MalformedURLException;
import java.net.URL;
public class main extends JFrame implements ActionListener {
public JPanel panel;
public JLabel lb_title;
public JLabel lb_qq;// QQ
public JLabel lb_pass;// 密码
public JLabel lb_vcode;// 验证码
public JTextField tx_qq;// QQ号编辑框
public JTextField tx_pass;// 密码文本框
public JTextField tx_vcode;// 验证码文本框
public JButton btn_Sub;// 登录按钮
public JButton btn_refresh;// 刷新验证码按钮
public Image image;
public boolean isVC;// 是否显示验证码
public Qzone qzone;
public String info;// 登录提示
public main() {
panel = new JPanel();
lb_title = new JLabel();
lb_qq = new JLabel();
lb_pass = new JLabel();
lb_vcode=new JLabel();
tx_qq = new JTextField();
tx_pass = new JTextField();
tx_vcode = new JTextField();
btn_Sub = new JButton();
btn_refresh = new JButton();
qzone = new Qzone("", "");
userInit();
}
public void userInit() {
try {
image = getToolkit().getImage(
new URL("http://cdn-img.easyicon.cn/png/5001/500130.png"));
setIconImage(image);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 设置关闭框架的同时结束程序
this.setSize(400, 300);// 设置框架大小为长300,宽200
this.setResizable(false);// 设置框架不可以改变大小
this.setTitle("模拟QQ空间登录");// 设置框架标题
this.panel.setLayout(null);// 设置面板布局管理
// this.panel.setBackground(Color.lightGray);// 设置面板背景颜色
this.lb_title.setText("QQ空间模拟登录");// 设置标签标题
this.lb_title.setFont(new Font("宋体", Font.BOLD | Font.ITALIC, 14));// 设置标签字体
this.lb_title.setForeground(Color.blue);// 设置标签字体颜色
this.lb_qq.setText("QQ 号:");
this.lb_pass.setText("密 码:");
this.lb_vcode.setText("验证码");
this.btn_Sub.setText("登录");
this.btn_refresh.setText("刷新验证码");
this.lb_title.setBounds(100, 15, 120, 20);// 设置标签x坐标120,y坐标15,长60,宽20
this.lb_qq.setBounds(50, 55, 60, 20);
this.lb_pass.setBounds(50, 85, 60, 25);
this.lb_vcode.setBounds(50,115,60,25);
this.tx_qq.setBounds(110, 55, 120, 20);
this.tx_pass.setBounds(110, 85, 120, 20);
this.tx_vcode.setBounds(110, 115, 120, 20);
this.btn_Sub.setBounds(85, 140, 60, 20);
this.btn_Sub.addActionListener(this);
this.btn_refresh.setBounds(155, 140, 100, 20);
this.btn_refresh.addActionListener(this);
this.panel.add(lb_title);// 加载标签到面板
this.panel.add(lb_qq);
this.panel.add(lb_pass);
this.panel.add(lb_vcode);
this.panel.add(tx_qq);
this.panel.add(tx_pass);
this.panel.add(tx_vcode);
this.panel.add(btn_Sub);
this.panel.add(btn_refresh);
this.add(panel);// 加载面板到框架
this.move(300, 200);
this.setVisible(true);// 设置框架可显
}
@Override
public void paint(Graphics g) {
if (isVC) {
image = getToolkit().getImage(
"D:\\个人资料管理\\Administrator\\我的文档\\图片\\VC.jpg");
} else {
image = null;
}
lb_vcode.setVisible(isVC);
tx_vcode.setVisible(isVC);
g.drawImage(image, 100, 200, this);
}
public static void main(String[] args) {
new main();
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == btn_Sub) {// 登录按钮
qzone.qq = tx_qq.getText();
qzone.password = tx_pass.getText();
if (!tx_vcode.getText().equals("")) {
qzone.vcode = tx_vcode.getText().toUpperCase();
}
info = qzone.login();
System.out.println("登录提示" + info);
if (info.equals("1")) {
isVC = true;
repaint();
}
}
}
}
Qzone类:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Random;
import org.jsoup.Connection.Method;
import org.jsoup.Connection.Response;
import org.jsoup.Jsoup;
public class Qzone {
public String qq, password, vcode;// QQ号,密码,验证码
private byte[] uin;// 16进制表示的QQ号
private HashMap<String, String> cookies;
public Qzone(String qq, String password) {
this.qq = qq;
this.password = password;
cookies = new HashMap<String, String>();
}
/** 登录 */
public String login() {
String url;// 访问网址
String text;// 提示文本
// 验证码
if (vcode == null) {
vcode = ptui_checkVC();
if (vcode == "1") {//需要验证码
saveVC();
return "1";
}
}
// 登录
System.out.println(vcode);
url = "http://ptlogin2.qq.com/login?u="
+ this.qq
+ "&p="
+ getEncryption()
+ "&verifycode="
+ this.vcode
+ "&aid=1006102&u1=http%3A%2F%2Fid.qq.com%2Findex.html%23myfriends&h=1&ptredirect=1&ptlang=2052&from_ui=1&dumy=&fp=loginerroralert&action=8-57-411578&mibao_css=&t=5&g=1&js_type=0&js_ver=10015&login_sig=M68RroVE7d9cWVGLMysPechIltwu1GWLDkOrMwJ1O2VISYLTKwX6t3*qLIwl1DIa";
text = connectURL(url);
return text;
}
/** 加密,QQ号,密码,验证码 */
private String getEncryption() {
byte[] str1;
String str2, str3;
str1 = hexchar2bin(MD5.md5(password.getBytes()));
str2 = MD5.md5(addByte(str1, this.uin));
str3 = MD5.md5((str2 + this.vcode).getBytes());
return str3;
}
/** 将返回的uin解析为byte[] */
private byte[] uinToByte(String haxqq) {
byte[] uin = new byte[8];
String haxtext = haxqq.replaceAll("\\\\x", "");
uin = hexchar2bin(haxtext);
return uin;
}
/** 检查是否需要验证码,并返回uin */
private String ptui_checkVC() {
String text = "";// 返回的文本
Response res = null;
String url = "http://check.ptlogin2.qq.com/check?uin="
+ this.qq
+ "&appid=1006102&js_ver=10015&js_type=0&login_sig=y9izLTQDUx-VRJ*tu9aAnzzd3Th5R5d3-LSQ-R-DgQmZx7cRXxodffTGfDUzJtox&u1=http%3A%2F%2Fid.qq.com%2Findex.html&r="
+ getRandom(15);
text = connectURL(url);
// 解析返回信息
this.uin = uinToByte(getTextInfo(text, "\\x", "');"));// 其实是\x,但java要转义符号));
if (getTextInfo(text, "'", "','").equals("1")) {// 需要验证码
return ("1");
}
return getTextInfo(text, "','", "','");
}
/**
* 取随机数
*
* @param length
* 随机数长度,如果为0则为17
* @return 随机数文本
*/
private String getRandom(int length) {
String text = "";// 返回的随机数
Random random = new Random();
for (int i = 0; i < length;) {
int num = random.nextInt(10);
if (i != 0 || num != 0) {
text += num + "";
i++;
}
}
return text;
}
/**
* 取文本中间
*
* @param text
* 被取的文本
* @param start
* 开始的文本(不包括)
* @param end
* 结束的文本(不包括)
* @return 文本的中间
*/
private String getTextInfo(String text, String start, String end) {
int startIndex;
int endIndex;
startIndex = text.indexOf(start) + start.length();
endIndex = text.indexOf(end, startIndex);
text = text.substring(startIndex, endIndex);
return text;
}
/** 访问网络 */
private String connectURL(String url) {
String text = "";
try {
Response res = Jsoup.connect(url).cookies(cookies)
.ignoreContentType(true).execute();
cookies.putAll(res.cookies());
text = new String(res.bodyAsBytes(), "utf-8");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return text;
}
/** 获取并保存验证码图片 */
public void saveVC() {
Response res;
File file;
byte[] b = null;// 返回值
String url = "http://captcha.qq.com/getimage?aid=1006102&r=0."
+ getRandom(17) + "&uin=" + this.qq;
try {
res = Jsoup.connect(url).cookies(cookies).ignoreContentType(true)
.execute();
b = res.bodyAsBytes();
cookies.putAll(res.cookies());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 写入文件
try {
file = new File("D:\\个人资料管理\\Administrator\\我的文档\\图片", "VC.jpg");
// 安卓的写法:
// file=new File(this.getCacheDir(),"VC.jpg");
// 如果不写在一个Activity内,则this写成getContext
FileOutputStream out = new FileOutputStream(file);
out.write(b);
out.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/** 将md5值转为byte[] */
private byte[] hexchar2bin(String hax) {
hax = hax.toUpperCase();// 只是看着舒服点,可以去掉
byte[] b = new byte[hax.length() / 2];
for (int i = 0; i < hax.length() - 1; i = i + 2) {
b[i / 2] = (byte) Integer.parseInt(hax.substring(i, i + 2), 16);
}
return b;
}
/**
* byte增加,JAVA中没找到直接合并的方法
*
* @param b1
* byte[]数据1
* @param b2
* byte[]数据2
* @return b1和b2的集合
*/
private byte[] addByte(byte[] b1, byte[] b2) {
byte[] by = new byte[b1.length + b2.length];
for (int i = 0; i < b1.length; i++) {
by[i] = b1[i];
}
for (int i = 0; i < b2.length; i++) {
by[b1.length + i] = b2[i];
}
return by;
}
}
md5类:
import java.security.MessageDigest;
/**
* MD5码的转换
*
* @author wolforce
*
*/
public class MD5 {
// 十六进制下数字到字符的映射数组
private final static String[] hexDigits = { "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "A", "B", "C", "D", "E", "F" };
/** 把inputString加密 */
public static String md5(byte[] inputStr) {
return encodeByMD5(inputStr);
}
/** 对字符串进行MD5编码 */
private static String encodeByMD5(byte[] inputStr) {
if (inputStr != null) {
try {
// 创建具有指定算法名称的信息摘要
MessageDigest md5 = MessageDigest.getInstance("MD5");
// 使用指定的字节数组对摘要进行最后更新,然后完成摘要计算
byte[] results = md5.digest(inputStr);
// 将得到的字节数组变成字符串返回
String result = byteArrayToHexString(results);
return result;
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
/**
* 轮换字节数组为十六进制字符串
*
* @param b
* 字节数组
* @return 十六进制字符串
*/
private static String byteArrayToHexString(byte[] b) {
StringBuffer resultSb = new StringBuffer();
for (int i = 0; i < b.length; i++) {
resultSb.append(byteToHexString(b[i]));
}
return resultSb.toString();
}
// 将一个字节转化成十六进制形式的字符串
private static String byteToHexString(byte b) {
int n = b;
if (n < 0)
n = 256 + n;
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
}
}