QQ空间登录协议实现:Java篇(Android)

其实是想写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];
	}
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值