一.須要用到的包:php
commons-codec-1.4.jarjava
commons-httpclient-3.0.1.jarjson
commons-logging-1.1.1.jar瀏覽器
二.分析新浪通行證登陸頁面cookie
登陸頁面:
app
新浪微博的登陸頁面中,我發現密碼在傳過去以前已經被js加密過,而js中加密方法很難找,而新浪通行證中的密碼並無加密,因此選擇經過新浪通行證登陸dom
地址:http://login.sina.com.cn/signup/signin.php?entry=ssopost
簡要說明登陸過程:測試
1.將用戶信息提交到https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15)&_=1425914562105中,ui
火狐瀏覽器中測出,它返回了一部分cookie和一個json格式的響應信息,但這部分cookie是不能做用在微博中的,由於他們和微博的主機、做用域不一樣
2.用js處理返回的json信息,構建一個get請求,其參數主要由json中的信息構成
3.返回微博的cookie
4.用這部分cookie能夠獲取微博的信息
三.具體登陸過程:
1.將用戶名、密碼等信息經過post請求傳入https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15)&_=1425914562105中,得到許多cookie和一個json格式的響應體。
public static void main(String[] args) { HttpClient client=new HttpClient(); NameValuePair pairs[]={ new NameValuePair("cdult","3"), new NameValuePair("encoding","UTF-8"), new NameValuePair("from",null), new NameValuePair("gateway","1"), new NameValuePair("prelt","0"), new NameValuePair("pagerefer","http://login.sina.com/sso/login.php"), new NameValuePair("returntype","TEXT"), new NameValuePair("savestate","30"), new NameValuePair("service","sso"), new NameValuePair("sp","密碼"), new NameValuePair("sr","1366*778"), new NameValuePair("su",getBASE64("用戶名")), new NameValuePair("useticket","0"), new NameValuePair("vsnf","1") }; HttpMethod method=getPostMethod("https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15)&_="+new Date().getTime(), null, pairs); client.getParams().setContentCharset("GBK"); try { client.executeMethod(method); // System.out.println(method.getResponseBodyAsString()); InputStream stream = method.getResponseBodyAsStream(); BufferedReader br = new BufferedReader(new InputStreamReader(stream, "UTF-8")); StringBuffer buf = new StringBuffer(); String line; while (null != (line = br.readLine())) { buf.append(line).append("\n"); } System.out.println(buf.toString()); method.releaseConnection(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } public static HttpMethod getPostMethod(String url,Header headers[],NameValuePair pairs[]){ PostMethod method=new PostMethod(url); if(headers!=null){ for(Header header:headers){ method.setRequestHeader(header); } } method.setRequestBody(pairs); return method; }
上述代碼中,最重要的部分是post參數中returntype,「TEXT」由於在ie中若是接收到json或者text格式的數據會自動提示下載,因此ie中這部分參數對應的value是「JFrame」格式的,因爲拿不到我想要的東西,其登陸過程我沒有分析。
經運行,咱們獲得下述json格式的代碼:
{"retcode":"0","uid":"2136324567", "nick":"\u7528\u62372136324567", "crossDomainUrlList": ["https:\/\/passport.weibo.com\/wbsso\/login?ticket=ST-MjEzNjMyNDU2Nw%3D%3D-1425964519-ja-B24DC4AB2894692B3B38928C36A11009&ssosavestate=1457500519", "https:\/\/crosdom.weicaifu.com\/sso\/crosdom?action=login&savestate=1457500519", "http:\/\/passport.weibo.cn\/sso\/crossdomain?action=login&savestate=1"]}
2. 根據返回json構建get請求例如
https://passport.weibo.com/wbsso/login?ticket=ST-MjEzNjMyNDU2Nw%3D%3D-1425965391-ja-BB03424873E09D9B8E6FF8BA8763304F&ssosavestate=1457501391&callback=sinaSSOController.doCrossDomainCallBack&scriptId=ssoscript0&client=ssologin.js(v1.4.15)&_=1425965215809
這裏我理解的是新浪會根據咱們提交的信息給咱們一張票去訪問微博,這些參數中,ticket和ssosavestate是json中給的_=後面是new Date().getTime(),其它固定,更新上面代碼,所有代碼以下
private static String username="xxxxx"; private static String password="xxxxx"; public static void main(String[] args) { String ticket=""; String ssosavestate=""; HttpClient client=new HttpClient(); NameValuePair pairs[]={ new NameValuePair("cdult","3"), new NameValuePair("encoding","UTF-8"), new NameValuePair("from",null), new NameValuePair("gateway","1"), new NameValuePair("prelt","0"), new NameValuePair("pagerefer","http://login.sina.com/sso/login.php"), new NameValuePair("returntype","TEXT"), new NameValuePair("savestate","30"), new NameValuePair("service","sso"), new NameValuePair("sp","wobuaini50"), new NameValuePair("sr","1366*778"), new NameValuePair("su",getBASE64(username)), new NameValuePair("useticket","0"), new NameValuePair("vsnf","1") }; HttpMethod method=getPostMethod("https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15)&_="+new Date().getTime(), null, pairs); client.getParams().setContentCharset("GBK"); try { client.executeMethod(method); String temp=method.getResponseBodyAsString(); if(temp.contains("ticket")){ ticket=temp.substring(temp.indexOf("ticket="),temp.indexOf("&")); ssosavestate=temp.substring(temp.indexOf("ssosavestate"),temp.indexOf("\"", temp.indexOf("ssosavestate"))); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } String url2="https://passport.weibo.com/wbsso/login?"+ticket+"&"+ssosavestate+"&callback=sinaSSOController.doCrossDomainCallBack&scriptId=ssoscript0&client=ssologin.js(v1.4.15)&_="+new Date().getTime(); String cookieStr=""; Header[] headers=null; HttpClient client2=new HttpClient(); GetMethod method2=new GetMethod(url2); try { client2.executeMethod(method2); headers=method2.getResponseHeaders(); method2.releaseConnection(); } catch (HttpException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } Cookie[] cookies=client2.getState().getCookies(); for (int i = 0; i < cookies.length; i++) { String temp=cookies[i].getName(); if(temp.equals("SUE")||temp.equals("SUS")||temp.equals("SUP")){ cookieStr+=cookies[i].getName()+"="+cookies[i].getValue()+";"; } } cookieStr+="un="+username; System.out.println(cookieStr); } public static HttpMethod getPostMethod(String url,Header headers[],NameValuePair pairs[]){ PostMethod method=new PostMethod(url); if(headers!=null){ for(Header header:headers){ method.setRequestHeader(header); } } method.setRequestBody(pairs); return method; } public HttpMethod getGetMethod(String url,Header headers[]){ HttpMethod method=new GetMethod(url); if(headers!=null){ for(Header header:headers){ method.setRequestHeader(header); } } return method; } @SuppressWarnings("restriction") public static String getBASE64(String s) { if (s == null) return null; return (new sun.misc.BASE64Encoder()).encode( s.getBytes() ); }
返回結果是:
SUS=SID-2136324567-1425965890-JA-6hy0f-a36939ccbd9b8192ecfa6b7dd7fd4122;SUE=es%3D72da1b83721474c9606bbec7bc8080b7%26ev%3Dv1%26es2%3Da0aa1dcd967281462c90f257a9daed9c%26rs0%3DgD8KqazZqR7q%252F3ytvcgRcNWY1frB7gvFQRxN3w0XLhZ3BvZy5tMWHZ58BMpG1X6a%252FisOZ0UPUCyuCdJOv6wfUfp1k1f9AadexOQoOAVFbkqr3LTiLI6u%252FkHe6fezN842YuY0w110jhU0Ls4vFOJvgOksPp4vpi5HOGKhqbmyGWQ%253D%26rv%3D0;SUP=cv%3D1%26bt%3D1425965890%26et%3D1426052290%26d%3Dc909%26i%3D4122%26us%3D1%26vf%3D0%26vt%3D0%26ac%3D0%26st%3D0%26uid%3D2136324567%26name%3D15201315239%2540sina.cn%26nick%3D%25E7%2594%25A8%25E6%2588%25B72136324567%26fmp%3D%26lcp%3D2014-04-29%252018%253A44%253A36;un=yourusername
這時咱們只須要在咱們的請求頭中 setRequestHeader("Cookie", cookieStr);就能夠訪問微博的各個頁面了
舉例部分代碼以下,能夠放到上述代碼的main中
HttpClient client3=new HttpClient(); GetMethod method3=new GetMethod("http://weibo.com/friends?leftnav=1&wvr=6&isfriends=1&step=2"); method3.setRequestHeader("Cookie", cookieStr); try { client3.executeMethod(method3); System.out.println(method3.getResponseBodyAsString()); } catch (HttpException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }
測試成功~
代碼不合理的地方還請指教