新浪微博授權認證的實現


  最近准備找工作,着手看了下新浪微博的資料,前幾天通過調用客戶端實現了微博分享功能。這兩天在網上搜了些資料,結合官方的開發文檔,實現了授權驗證部分。
  下面按類作為章節來總結下驗證這部分的實現:
  Constants類
    這個類內容很少,但起到很大作用,能否成功獲取授權關鍵就在於該類中的一些變量如APP_KEY和SECRET的賦值是否正確。

package com.example.shareweibobyapi;
//授權類
public interface Constants {
    /** 當前 DEMO 應用的 APP_KEY,如果自己在新浪官網上的開發者認證還沒有通過,則該APP_KEY和SECRET有效期一般只有一天 */
    public static final String APP_KEY      = "2059271021";
    public static final String CONSUMER_SECRET      = "0df386dee39f2b165c066a5665ff4eb7";
    public static final String REDIRECT_URL = "http://www.sina.com.cn";
    public static final String SCOPE = 
            "email,direct_messages_read,direct_messages_write,"
            + "friendships_groups_read,friendships_groups_write,statuses_to_me_read,"
            + "follow_app_official_microblog," + "invitation_write";
}

  AccessTokenKeeper類
    該類通過SharedPreferences實現了AccessToken的保存和讀取以及刪除。下面對SharePreferences類進行簡單介紹:SharedPreferences是Android平台上一個輕量級的存儲類,主要保存一些配置信息,可以保存Long、Int、String類型的數據。2個Activity之間的數據傳遞除了可以通過Intent來傳遞,還可以使用該類進行傳遞。

package com.example.shareweibobyapi;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import com.sina.weibo.sdk.auth.Oauth2AccessToken;
/**
 * 該類實現了AccessToken的保存和讀取以及刪除。*/
public class AccessTokenKeeper {
    
    private static final String PREFERENCES_NAME = "com_weibo_sdk_android";//SharedPreferences類所在包
    private static final String KEY_UID           = "uid";//創建一個變量存儲用戶昵稱
    private static final String KEY_ACCESS_TOKEN  = "access_token";//創建一個變量存儲access_token
    private static final String KEY_EXPIRES_IN    = "expires_in";
    
    /**
     * 保存 Token 對象到 SharedPreferences。
     * @param context 應用程序上下文環境
     * @param token   Token 對象
     */
    public static void writeAccessToken(Context context, Oauth2AccessToken token) {
        if (null == context || null == token) {
            return;
        }
        SharedPreferences pref = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_APPEND);
        Editor editor = pref.edit();
        editor.putString(KEY_UID, token.getUid());
        editor.putString(KEY_ACCESS_TOKEN, token.getToken());
        editor.putLong(KEY_EXPIRES_IN, token.getExpiresTime());
        editor.commit();
    }

    /**
     * 從 SharedPreferences 讀取 Token 信息。
     * @param context 應用程序上下文環境
     * @return 返回 Token 對象
     */
    public static Oauth2AccessToken readAccessToken(Context context) {
        if (null == context) {
            return null;
        }
        Oauth2AccessToken token = new Oauth2AccessToken();
        SharedPreferences pref = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_APPEND);
        token.setUid(pref.getString(KEY_UID, ""));
        token.setToken(pref.getString(KEY_ACCESS_TOKEN, ""));
        token.setExpiresTime(pref.getLong(KEY_EXPIRES_IN, 0));
        return token;
    }
    /**
     * 清空 SharedPreferences 中 Token信息。
     * @param context 應用程序上下文環境
     */
    public static void clear(Context context) {
        if (null == context) {
            return;
        }
        SharedPreferences pref = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_APPEND);
        Editor editor = pref.edit();
        editor.clear();
        editor.commit();
    }
}

  MainActivity類
    該類為主窗口類,實現了OAuth授權認證。新浪微博的OAuth授權認證過程,大致可以分為以下幾個步驟:
      1.第三方應用攜帶App Key和App Secret兩個參數向新浪微博發起認證請求。
      2.通過驗證后,第三方應用根據服務器返回的Request Token和Request Secret這兩個參數跳轉到新浪微博的授權界面。如果用戶設備上已經安裝微博客戶端,則直接調用微博客戶端拉取授權信息(oauth_verifier),否則跳轉到WEB認證界面,用戶可通過輸入自己的賬號和密碼獲取授權信息(oauth_verifier)。
      3.第三方應用攜帶Request Token和Request以及oauth_verifier這三個參數再次向新浪微博發起認證請求。新浪微博將返回user_id、Access Token和Access Secret這三組參數,客戶端利用這三組參數即可調用具有相應權限的API。

package com.example.shareweibobyapi;public class MainActivity extends Activity {
    
    Button ssoBtn;//分享按鈕
    EditText shareText;
    private TextView mTokenText;//顯示授權成功后返回的access_token
    private WeiboAuth mWeiboAuth;//微博web授權類,提供登錄功能
    private Oauth2AccessToken mAccessToken;//提供Oauth2認證功能
    private SsoHandler mSsoHandler;
    private UsersAPI mUsersAPI;//用戶信息接口 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }
    public void initView()
    {
        ssoBtn=(Button) findViewById(R.id.button1);
        mTokenText=(TextView) findViewById(R.id.textView1);
        //創建微博實例,傳入APP_KEY,REDIRECT_URL等信息
        mWeiboAuth=new WeiboAuth(this,Constants.APP_KEY,Constants.REDIRECT_URL,Constants.SCOPE);
        //從SharedPreferences讀取AccessToken信息
        mAccessToken=AccessTokenKeeper.readAccessToken(this);
        //第一次啟動本應用,AccessToken不可用
        if(mAccessToken.isSessionValid())
        {
            updateTokenView(true);
        }
        //單擊“分享”按鈕,進行授權
        ssoBtn.setOnClickListener(new OnClickListener()
        {
            public void onClick(View v)
            {
                if(v==ssoBtn)
                {
                    mSsoHandler=new SsoHandler(MainActivity.this,mWeiboAuth);
                    mSsoHandler.authorize(new AuthListener());
                }
            }
            
        });
    }
    
    //當SSO授權Activity退出時,該函數被調用.發起SSO登錄的Actiity必須重寫onActivityResult
    protected void onActivityResult(int requestCode,int resultCode,Intent data)
    {
        super.onActivityResult(requestCode,resultCode,data);
        if(mSsoHandler!=null)
        {
            mSsoHandler.authorizeCallBack(requestCode, resultCode, data);
        }
    }
    
    //微博授權回調類
    class AuthListener implements WeiboAuthListener
    {    //授權完成
        @Override
        public void onComplete(Bundle values){
            //從Bundle解析Token
            mAccessToken=Oauth2AccessToken.parseAccessToken(values);
            if(mAccessToken.isSessionValid())
            {
                //顯示Token
                updateTokenView(false);
                //保存Token到SharePreferences
                AccessTokenKeeper.writeAccessToken(MainActivity.this, mAccessToken);
                Toast.makeText(MainActivity.this,"success!!",Toast.LENGTH_SHORT).show();
                //根據uid獲取用戶的昵稱
                long uid=Long.parseLong(mAccessToken.getUid());
                mUsersAPI.show(uid,mListener);
            }
            else
            {
                Toast.makeText(MainActivity.this,"fail!!",Toast.LENGTH_SHORT).show();
            }
        }//授權異常
        @Override
        public void onWeiboException(WeiboException e)
        {
            Toast.makeText(MainActivity.this,  "Auth exception : " + e.getMessage(), Toast.LENGTH_LONG)  
                    .show();
        }
    }
    
    //顯示當前Token信息
    public void updateTokenView(boolean hasExisted)
    {    //獲取用戶信息接口
        mUsersAPI=new UsersAPI(mAccessToken);
        String date=new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(new java.util.Date(mAccessToken.getExpiresTime()));
        String format=getString(R.string.weibosdk_demo_token_to_string_format_1);
        mTokenText.setText(String.format(format,mAccessToken.getToken(),date));
        String message=String.format(format,mAccessToken.getToken(),date);
        if(hasExisted)
        {
            message=getString(R.string.weibosdk_demo_token_has_existed)+"\n"+message;
            //根據uid獲取用戶的昵稱,因為uid是在回調方法從服務器傳遞過倆的數據中
            long uid=Long.parseLong(mAccessToken.getUid());
            mUsersAPI.show(uid, mListener);
        }
        mTokenText.setText(message);
    }

    };
}

來看看期待已久的授權成功的效果圖:

總結:
  整個過程中遇到的問題以及解決方案:
  1.定義按鈕的時候犯了個低級錯誤:在MainActivity的變量定義區域實例化了一個Button對象,導致運行時出現空指針錯誤,最后通過LOgcat信息定位錯誤所在行,將實例化語句轉移到OnCreat()中即可解決問題。
  2.運行程序,點擊“分享”按鈕出現這個異常:auth exception 21338。出現問題后百度、谷歌交叉搜索一下,最后才明白問題根源所在:App_Key過期。由於在新浪微博上申請的開發者身份還沒有通過認證,所以申請的App_Key只能在當天使用。找到問題根源,解決起來就很簡單了,重新申請一個就搞定。
  3.解決上面那個問題后,滿懷信心地再次運行程序,結果卻出現這個錯誤:sso package or sign error。再次百度、谷歌,結果發現這是新版本的SDK才會出現的問題,一般都是由於MD5簽名不正確或者過期而導致。而當想要修改MD5簽名的時候,我竟然發現一開始創建應用的時候我竟沒有使用簽名,真是蠢到家。解決起來也很簡單,安裝一個簽名工具,簽名后在新浪微博個人信息里面填寫下應用報名和簽名即可。
領悟:
  學習一個新的知識,不要太過浮躁,不要總想着我多長時間內能做出來。對於沒接觸過的東西,即使再簡單,對我們來說都是陌生的東西,和陌生的東西打交道總需要些耐心和時間。所以多看看與該知識相關的一些優秀博客,站在別人的成果上去看問題,總會看得更遠一些。
  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM