httpclient登录新浪微博(非SDK方式)

原文出处:IT男杂记事

苦逼的折腾了快一星期,总算把新浪微博rsa加密登录折腾ok了,这里需要注意的是httpclient最好用4.0的,否则cookie管理很是问题。

进入正题,最近新浪微博更新了sso登录方式,加密算法变成了rsa,获取nonce和servertime,pubkey,这里涉及到rsa加密,通常用java进行rsa加密一般都是从文件读取公钥信息或者是base64编码的公钥信息转换成key,然后进行加密,但是新浪给的不是base64加密,而是给的一个N(参见RSA加密算法,RSA加密算法),而我先入为主,把新浪给的pubkey当作base64编码的公钥信息,苦逼的折腾了快一天。后来再细看看RSA加密算法感觉pubkey不像是base64编码,看到网上有人分析新浪的sso.js,于是我也看一下,终于有收获,看到他把pubkey解析成biginteger,感觉怪怪的,联想到rsa的百科,发现应该是我搞错了,遂找到以下方法。用pubkey进行加密。

public String rsaCrypt(String modeHex, String exponentHex, String messageg) throws IllegalBlockSizeException,
			BadPaddingException, NoSuchAlgorithmException,
			InvalidKeySpecException, NoSuchPaddingException,
			InvalidKeyException, UnsupportedEncodingException {
		KeyFactory factory = KeyFactory.getInstance("RSA");

		BigInteger m = new BigInteger(modeHex, 16); /* public exponent */
		BigInteger e = new BigInteger(exponentHex, 16); /* modulus */
		RSAPublicKeySpec spec = new RSAPublicKeySpec(m, e);

		RSAPublicKey pub = (RSAPublicKey) factory.generatePublic(spec);
		Cipher enc = Cipher.getInstance("RSA");
		enc.init(Cipher.ENCRYPT_MODE, pub);

		byte[] encryptedContentKey = enc.doFinal(messageg.getBytes("GB2312"));

		return new String(Hex.encodeHex(encryptedContentKey));
	}

方法名气得不是很理想,但是不影响我们学习。搞定加密了,接下来更苦逼的是http-client3这托,我看网上有人弄出来的代码,参考着弄下,但是他们的验证方法,参数都有问题,我参照有人用ruby写的(sso 1.4.2版本的),将该替换的都替换了,一直进行到ajaxlogin这里,可以获取到我的个人信息,但是苦逼的是,真正登录的时候不行,我怀疑是cookie问题,因为一直警告我cookie reject,因为新浪sso登录时候用了些技巧解决跨域。好,那我就山寨点,把cookie domain该了,改成.weibo.com最终获取用户主页时retcode=6102,查了下sso.js代码,发现是没登录成功 ,cookie问题。什么办法读想了,抓包,分析,firebug分析,google了无数遍,最后还是没成功。无奈继续google,苦心不负有心人,最终发现这篇,http-client4来做的,我隐约记得官方推荐用hc4,于是就搞了下,竟然可以获得首页一些信息,虽然不是html的,但应该是成功了,之前没成功的话获取个人主页会得到登录的html。下面是主要代码。

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

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

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.NameValuePair;
import org.apache.http.HttpException;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
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.client.params.CookiePolicy;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject;

public class Main {

	static String SINA_PK = "EB2A38568661887FA180BDDB5CABD5F21C7BFD59C090CB2D24"
			+ "5A87AC253062882729293E5506350508E7F9AA3BB77F4333231490F915F6D63C55FE2F08A49B353F444AD39"
			+ "93CACC02DB784ABBB8E42A9B1BBFFFB38BE18D78E87A0E41B9B8F73A928EE0CCEE"
			+ "1F6739884B9777E4FE9E88A1BBE495927AC4A799B3181D6442443";
	static String username = "用户名";
	static String passwd = "密码";

	private static final Log logger = LogFactory.getLog(Main.class);

	public static void main(String[] args) throws HttpException, IOException,
			JSONException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException {
		DefaultHttpClient client = new DefaultHttpClient();
		client.getParams().setParameter("http.protocol.cookie-policy",
				CookiePolicy.BROWSER_COMPATIBILITY);
		client.getParams().setParameter(
				HttpConnectionParams.CONNECTION_TIMEOUT, 5000);

		HttpPost post = new HttpPost(
				"http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.2)");

		PreLoginInfo info = getPreLoginBean(client);

		long servertime = info.servertime;
		String nonce = info.nonce;

		String pwdString = servertime + "\t" + nonce + "\n" + "PASSWORD";
		String sp = new BigIntegerRSA().rsaCrypt(SINA_PK, "10001", pwdString);

		List<NameValuePair> nvps = new ArrayList<NameValuePair>();
		nvps.add(new BasicNameValuePair("entry", "weibo"));
		nvps.add(new BasicNameValuePair("gateway", "1"));
		nvps.add(new BasicNameValuePair("from", ""));
		nvps.add(new BasicNameValuePair("savestate", "7"));
		nvps.add(new BasicNameValuePair("useticket", "1"));
		nvps.add(new BasicNameValuePair("ssosimplelogin", "1"));
		nvps.add(new BasicNameValuePair("vsnf", "1"));
		// new NameValuePair("vsnval", ""),
		nvps.add(new BasicNameValuePair("su", encodeUserName(username)));
		nvps.add(new BasicNameValuePair("service", "miniblog"));
		nvps.add(new BasicNameValuePair("servertime", servertime + ""));
		nvps.add(new BasicNameValuePair("nonce", nonce));
		nvps.add(new BasicNameValuePair("pwencode", "rsa2"));
		nvps.add(new BasicNameValuePair("rsakv", info.rsakv));
		nvps.add(new BasicNameValuePair("sp", sp));
		nvps.add(new BasicNameValuePair("encoding", "UTF-8"));
		nvps.add(new BasicNameValuePair("prelt", "115"));
		nvps.add(new BasicNameValuePair("returntype", "META"));
		nvps.add(new BasicNameValuePair(
				"url",
				"http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack"));

		post.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));

		HttpResponse response = client.execute(post);  
        String entity = EntityUtils.toString(response.getEntity());  

        String url = entity.substring(entity  
                .indexOf("http://weibo.com/ajaxlogin.php?"), entity  
                .indexOf("code=0") + 6); 

        logger.debug("url:" + url);

     // 获取到实际url进行连接  
        HttpGet getMethod = new HttpGet(url);  

        response = client.execute(getMethod);  
        entity = EntityUtils.toString(response.getEntity());  
        entity = entity.substring(entity.indexOf("userdomain") + 13, entity  
                .lastIndexOf("\""));  
        logger.debug(entity);  

        getMethod = new HttpGet("http://weibo.com/humingchun?wvr=5&lf=reg");  
        response = client.execute(getMethod);  
        entity = EntityUtils.toString(response.getEntity());  
        // Document doc =  
        // Jsoup.parse(EntityUtils.toString(response.getEntity()));  
        System.out.println(entity);
        logger.debug(entity);
	}

	private static PreLoginInfo getPreLoginBean(HttpClient client)
			throws HttpException, IOException, JSONException {

		String serverTime = getPreLoginInfo(client);
		System.out.println("");
		JSONObject jsonInfo = new JSONObject(serverTime);
		PreLoginInfo info = new PreLoginInfo();
		info.nonce = jsonInfo.getString("nonce");
		info.pcid = jsonInfo.getString("pcid");
		info.pubkey = jsonInfo.getString("pubkey");
		info.retcode = jsonInfo.getInt("retcode");
		info.rsakv = jsonInfo.getString("rsakv");
		info.servertime = jsonInfo.getLong("servertime");
		return info;
	}

	public static String getPreLoginInfo(HttpClient client)
			throws ParseException, IOException {
		String preloginurl = "http://login.sina.com.cn/sso/prelogin.php?entry=sso&"
				+ "callback=sinaSSOController.preloginCallBack&su="
				+ "dW5kZWZpbmVk"
				+ "&rsakt=mod&client=ssologin.js(v1.4.2)"
				+ "&_=" + getCurrentTime();
		HttpGet get = new HttpGet(preloginurl);

		HttpResponse response = client.execute(get);

		String getResp = EntityUtils.toString(response.getEntity());

		int firstLeftBracket = getResp.indexOf("(");
		int lastRightBracket = getResp.lastIndexOf(")");

		String jsonBody = getResp.substring(firstLeftBracket + 1,
				lastRightBracket);
		System.out.println(jsonBody);
		return jsonBody;

	}

	private static String getCurrentTime() {
		long servertime = new Date().getTime() / 1000;
		return String.valueOf(servertime);
	}

	private static String encodeUserName(String email) {
		email = email.replaceFirst("@", "%40");// MzM3MjQwNTUyJTQwcXEuY29t
		email = Base64.encodeBase64String(email.getBytes());
		return email;
	}

}

 完整源码到这里下载 http://marspring.mobi/http-client-weibo/ 文章中给出了下载链接了

 

 

你可能感兴趣的:(java,加密,SSO)