雖然新浪微博開放平台中提供各種語言版本的開發SDK 下載,也各自附有一些基本接口調用的Demo 和接口說明文檔。但是這幾天的耐心嘗試之後,感覺新浪微博開放平台上的入門指導和下載到的Java 開發包weibo4j 包裡面的Demo 使用註釋有些不一致。再加上自身領悟能力有限,導致遇到好些摸不著頭腦的難題。不過幸好沒有放棄去嘗試弄懂它。廢話少說,下面是我學習的過程。
想要通過調用新浪微博開放平台API 開發自己的微博應用,第一步是擁有sina 微博賬號和CSDN 賬號,因為我們要同時用這兩個賬號創建微博應用,以此獲得App key 和Secret key 。那App key 和Secret key 有什麼用?
其實我單單看了sina 微博開放平台的一系列說明都不怎麼理解App key 和Secret key 有啥用。因為更加重點是必須理解OAuth 認證、授權的整個流程,以及在整個OAuth 認證、授權流程中好幾個Token 、4個URL的作用。
剛開始遇到完全沒個概念的OAuth 時,以為就沒戲學習不下去了。好在搜到下面這些文章,對於理解OAuth 非常有幫助,鏈接如下:
在OAuth 中有3個參與者,分別是User 、Service Provider 、Consumer 。假設我要開發一個基於sina 微博開放平台的應用(App),供其他sina 微博用戶使用。它們的對應關係如下:
其實我們這個App 對於User 和Provider(sina微博平台)來說,相當於一個第三方應用。作為第三方的App 想要訪問User保存於sina微博平台中的資源,肯定必須經過一系列認證和授權之後才能夠行得通。
下面是基於我對整個OAuth 認證、授權流程的理解畫成的圖(可以看一下跳過,當對後面的一些概念有一定理解之後再回頭看看這流程圖):
結合上面的流程圖,下面是我對這些術語的理解以及各個流程的描述:
Consumer key 、Consumer Secret :在sina 微博開放平台分別稱為App key、Secret key。 Consumer向Provider 申請希望能夠調用其開放API,申請通過後由Provider 分配給符合其要求的Consumer ,用於唯一標識該Consumer 符合Provider 的要求。
對應於上圖的流程1 和2。
Request Token 、Request Secret :當User 訪問Consumer 並希望能夠獲得其特殊服務,該服務由Consumer 對User 自身存放在Provider 中的資源進行整合操作之後返回。此時Consumer 向Provider 請求獲得Requst Token,用於唯一標識該Consumer 與該User 的特定關聯。
對應於上圖的流程3 、4 、5。
至流程6 ,Consumer 必須把User 引導到Provider所提供的OAuth 認證、授權頁面,其實就是瀏覽器重定向到附加有Request Token 和Request Secret 參數的authenticationURL。該URL 由Provider 提供。
接下來流程7 和8 中User 授權該Consumer(一般是通過輸入賬號、密碼登錄而已),則Provider 將重定向到流程1 中Consumer 提供的Callback_URL ,並且在該URL 參數中附加了OAuth Token 和OAuth Verifier 。
流程9 是Consumer 通過之前已從Provider 那裡獲取來的Request Token 再次請求Provider 以獲取Access Token 。
Access Token 、 Access Secret :若流程10 中Provider 返回一個未經User 授權的Access Token ,它用於唯一標識特定Consumer 可以訪問某User 存放在Provider 中的資源、信息。那麼Consumer 就可以開始使用獲取到的Access Token 和Access Secret 訪問對應User 存放在Provider 中的資源。
經過流程11 中對User 信息的整合、操作之後,就可以將特定的服務結果返回給User 了。
通過上面對於OAuth 流程的理解,我們知道其實User 完全沒有將自己登錄Provider 所需的賬號、密碼等洩露給第三方的Consumer 。同時User 又能使用到Consumer 的特殊服務。真是很巧妙的而又安全的操作流程啊!
此外,上圖中Consumer 有3 次與Provider 發出不同的請求,其實就是由Provider 提供3 個不同作用的URL 給Consumer 訪問。在sina 微博開放平台中這3 個URL 的截圖如下:
sina微博開放平台中使用OAuth驗證並發表微博
要使用sina微博開放平台的API,應先獲取sina分配的App key 和App Secret,下面是我創建應用之後sina分配的App key 和App Secret(這個可是要保密的哦)。
然後是下載微博SDK,我用Java 的weibo4j。
修改SDK包裡面Weibo.java 類的App Key 和App Secret 為剛剛獲取的App Key 和App Secret ,如下圖使用說明所示:
完成了這些之後,就可以根據提供的Demo開始寫代碼了。如下:
WebOAuth.java,用於初始化Weibo.java類所需的App Key 和App Secret,並提供獲取Request Token 和Access Token 的方法getRequestToken()、gettAccessToken(),其所需參數如代碼所示。另外,還提供了發布一個文本微博的方法update()。
package weibo4j.examples; import weibo4j.Status; import weibo4j.Weibo; import weibo4j.WeiboException; import weibo4j.http.AccessToken; import weibo4j.http.RequestToken; import java.io.UnsupportedEncodingException; // Web 方式認證public class WebOAuth { private Weibo weibo; public WebOAuth(){ // 準備好Consumer Key、Consumer Secret // 對應於新浪微博應用就是申請到的App key 和Secret key System.setProperty("weibo4j.oauth.consumerKey", Weibo.CONSUMER_KEY); System.setProperty("weibo4j.oauth.consumerSecret", Weibo.CONSUMER_SECRET); weibo = new Weibo(); } // 根據傳入的callback_url 獲取request token public RequestToken getRequestToken(String backUrl) { try { // 指定callback_url 並獲得request token RequestToken requestToken = weibo.getOAuthRequestToken(backUrl); System.out.println("Request token: " + requestToken.getToken()); System.out.println("Request token secret: " + requestToken.getTokenSecret()); return requestToken; } catch (Exception e) { System.out.println("獲取Request token發生異常!"); e.printStackTrace(); return null; } } // 根據傳入的request token 和verifier 獲取access token public AccessToken gettAccessToken(RequestToken requestToken, String verifier) { try { AccessToken accessToken = weibo.getOAuthAccessToken(requestToken .getToken(), requestToken.getTokenSecret(), verifier); System.out.println("Access token: " + accessToken.getToken()); System.out.println("Access token secret: " + accessToken.getTokenSecret()); return accessToken; } catch (Exception e) { System.out.println("獲取Access token發生異常!"); e.printStackTrace(); return null; } } // 根據傳入的Access Token 和內容髮表微博public void update(AccessToken access, String content) { try { weibo.setToken(access.getToken(), access.getTokenSecret()); content = new String(content.getBytes("GBK"), "UTF-8"); Status status = weibo.updateStatus(content); System.out.println("成功發表微博:" + status.getText() + "."); } catch (UnsupportedEncodingException e) { System.out.println("微博內容轉編碼發生異常!"); e.printStackTrace(); } catch (WeiboException e) { System.out.println("發表微博發生異常!"); e.printStackTrace(); } } } request.jsp,用於提供callback_url(這裡我們自定義為下文中的callback.jsp),當獲取得到RequestToken之後,保存該RequestToken到Session中,並將頁面重定向到callback.jsp進行驗證、授權。 <%@ page contentType="text/html;charset=utf-8" %> <%@ page language="java" import="weibo4j.*" %> <%@ page language="java" import="weibo4j.http.*" %> <%@ page language="java" import="weibo4j.util.*" %> <jsp:useBean id="weboauth" scope="session" /> <% if("1".equals(request.getParameter("opt"))) { // 傳入callback_url String callback_url = "http://localhost:8080/sinaweibo/callback.jsp"; RequestToken requestToken = weboauth.getRequestToken(callback_url); if(requestToken != null){ out.println(requestToken.getToken()); out.println(requestToken.getTokenSecret()); session.setAttribute("requestToken",requestToken); String url = requestToken.getAuthorizationURL()+"&oauth_callback="+callback_url; System.out.println("AuthorizationURL:" + url); //BareBonesBrowserLaunch.openURL(callback_url); //response.sendRedirect(requestToken.getAuthorizationURL()); // 重定向到附加了callback_url回調地址的sina微博認證頁面response.sendRedirect(url); }else{ out.println("request error"); } }else{ %> <a href="request.jsp?opt=1">請點擊進行Web方式的OAuth認證! </a> <% } %>
callback.jsp,在上一步中重定向之後,callback_url 後面會被附加了oauth_verifier參數,此時我們根據保存在Session中的RequestToken和獲取到的oauth_verifier參數申請獲得AccessToken。一旦獲得AccessToken,我們再把頁面重定向到編寫微博的頁面writeWeibo.html。
<%@ page contentType="text/html;charset=utf-8" %> <%@ page language="java" import="weibo4j.http.*" %> <%@ page language="java" import="weibo4j.*" %> <jsp:useBean id="weboauth" scope="session" /> <% // 獲得HTTP請求中的oauth_verifier 參數String verifier=request.getParameter("oauth_verifier"); out.println("oauth_verifier:"+verifier); System.out.println("oauth_verifier:"+verifier); if(verifier != null){ RequestToken requestToken = (RequestToken)session.getAttribute("requestToken"); if(requestToken != null){ AccessToken accessToken = weboauth.gettAccessToken(requestToken,verifier); if(accessToken != null){ try{ session.setAttribute("accessToken",accessToken); out.println("5 秒後轉到writeWeibo.html"); Thread.sleep(5000); response.sendRedirect("http://localhost:8080/sinaweibo/writeWeibo.html"); }catch(Exception e){ e.printStackTrace(); } }else{ out.println("access token request error"); } }else{ out.println("request token session error"); } }else{ out.println("verifier String error"); } %> writeWeibo.html,很簡單的HTML文件。 <html> <head><title>發布sina微博</title></head> <body bgcolor="#d0d0d0" > <form action="updateWeibo.jsp" method="post"> 請在這裡寫上140字符以內的文本:</br> <textarea name="weiboText" rows="3" cols="30">測試新浪微博! </textarea></br> <input type="submit" value="發布"> <input type="reset" value="清除"></br> </form> </body> </html> updateWeibo.jsp,用於發表文本微博,即調用WebOAuth.java 中的update方法。 <%@ page contentType="text/html;charset=utf-8" %> <%@ page language="java" import="weibo4j.http.*" %> <%@ page language="java" import="weibo4j.*" %> <jsp:useBean id="weboauth" scope="session" /> <% AccessToken accessToken = (AccessToken)session.getAttribute("accessToken"); String weiboText = (String)request.getParameter("weiboText"); // 連續發表同樣的微博內容會返回400錯誤weboauth.update(accessToken, weiboText); out.println("微博發表成功!"); %>
運行之前我們要準備好Tomcat ,並將上面的源文件放到正確的目錄中。此外,還應該在/WEB-INF/lib目錄下添加SDK包中帶有的commons-httpclient-3.1.jar 包,以及我自己編譯、打包後的weibo4j.jar(裡面是sina微博開放平台中的具體Java實現)。
運行Tomcat,在瀏覽器中訪問request.jsp 頁面,如下圖:
點擊其中的鏈接,如下圖(注意地址欄的變化):
其中地址欄的URL如下:
http://api.t.sina.com.cn/oauth/authorize?oauth_token=efda6f2499877d0e6d814f8c3d31a1d1&oauth_callback=http://localhost:8080/sinaweibo/callback.jsp
填上具體有效的sina微博賬號、密碼並授權。以下是填上了我測試用的微博賬號並授權的結果:
其中地址欄的URL如下:
http://localhost:8080/sinaweibo/writeWeibo.html
點擊“發布”,如下圖:
登錄微博查看一下,如下圖:
查看一下該賬號所授權的應用列表:
至此,關於OAuth方式使用sina微博開放平台來發布微博就大概是這個過程。
小結:
1、其實還有好多細節沒能講到,我也是嘗試了好多次才一點點發現問題、理解問題、再到解決問題;
2、如果瀏覽器中已經保存了我們登錄sina微博的賬號信息的Cookie,那麼在授權時不用輸入賬號信息,當然也可以修改不用當前賬號進行授權;
3、還有控制台輸入的一些信息,例如Token、URL、服務器返回信息都沒有截圖給出。