前言
Wbp4j
前排安利以下使用java完成的基于微博图床api实现的一个上传图片的小轮子,然后里面也有完整的代码可以查看,欢迎戳一下~ 传送门
目的
因为最近个人小项目里需要上传图片,看着自己的1M小水管产生了使用微博图床的念头,然后就开干了。
废话
老夫写代码复制粘贴就是干,结果一搜几乎都是php跟python
语言而已嘛!道理是相通的问题不大的(疯狂暗示
登陆
站在巨人的肩膀上确实是能轻松不少,经过搜索引擎的指引我们知道微博登录分两个步骤 ,第一个是预登陆,获取相关的登录信息之后再登录
预登陆
去微博首页随便填个用户名,然后通过抓包可以发现
这有一个神奇的prelogin请求,这就是我们想要的
https://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=MTkxNjE1MjM0NSU0MHFxLmNvbQ%3D%3D&rsakt=mod&checkpin=1&client=ssologin.js(v1.4.19)&_=1528984661146
再看一下参数,一眼(?)就能看出 一下两个参数是我们需要的
su
:base64后的用户名
_
:时间戳
这就好办了,拼接一下~
private PreLogin preLogin() throws IOException {
String preLoginUrl = "https://login.sina.com.cn/sso/prelogin.php?";
String base64Username = Base64.getEncoder().encodeToString(username.getBytes());
String params = "entry=weibo&su=" + base64Username + "MTIzNDU2&rsakt=mod&checkpin=1&client=ssologin.js(v1.4.19)&_=";
String url = preLoginUrl + params + System.currentTimeMillis();
}
然后这里假装GET
了一下那个url,返回的是一段json
然后再保存一下这些信息,然后预登陆就完成啦,是不是挺简单呢
到这里确实还是简单的,但是到后面就蛋疼了
登录
首先来看一下预登陆返回的json
{
"retcode":0,
"servertime":1528984659,
"pcid":"yfe839c398fb963099182103a19af18353ce05",
"nonce":"VOMF8H",
"pubkey":"EB2A38568661887FA1...3181D6442443",
"rsakv":"1330428213",
"is_openlock":0,
"showpin":0,
"exectime":13
}
emmm就看一下,这些都有啥用接下来说,然后我们再来登录一下看看都发了些什么东西
里面有几个字段是根据prelogin返回的内容发回去的所以不用管,就是那个sp是个啥玩意呢,虽然我知道是密码没错,看到rsa2,看到pubkey就觉得事实并非这么简单,根据搜索引擎的指引,我们找到微博用于登录的加密密码的js
这是密码加密的核心代码了
然后对着写不就完事了嘛,当然是这么想的
看着别人python的rsa.encode(pubkey,*啥)的
由于个人对加密这一块几乎没啥概念,所以只能继续依靠搜索引擎的能力的,找了半天使用java加密微博密码的,要么是直接用脚本引擎去执行以上的js代码,要么就是自己用浏览器登录后再把cookie复制粘贴,emmm,作为全自动的模拟登陆不能忍,然后花了一个下午去摸索终于成功了,不想多说了直接贴代码吧,反正我也解释不来为啥这么干
以下哪个pubExp我也不知道叫啥随便起的名字,对应着以上js的那个"10001"
public static String encode(String toEncode, String pubKey, String pubExp)
throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeySpecException, InvalidKeyException, BadPaddingException,
IllegalBlockSizeException {
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
BigInteger modulus = new BigInteger(pubKey, 16);
BigInteger publicExponent = new BigInteger(pubExp, 16);
RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(modulus, publicExponent);
PublicKey publicKey = keyFactory.generatePublic(rsaPublicKeySpec);
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encodeStr = cipher.doFinal(toEncode.getBytes());
return BytesUtils.bytesToHex(encodeStr);
}
然后最难的步骤已经成功啦,接下来只需要把对应的参数填上去就ok啦,然后再post就完事啦~