/** * $id$ * Copyright 2011-2012 Renren Inc. All rights reserved. */ package com.renren.api.connect.android; import org.json.JSONException; import org.json.JSONObject; import com.renren.api.connect.android.exception.RenrenError; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; /** * 用来存取AccessToken和SesionKey;开发者不会直接使用该类。 * * @author 李勇(yong.li@opi-corp.com) 2011-2-24 */ class AccessTokenManager implements Parcelable { private static final String SESSION_KEY_URL = "http://graph.renren.com/renren_api/session_key"; private static final String RENREN_SDK_CONFIG = "renren_sdk_config"; private static final String RENREN_SDK_CONFIG_PROP_ACCESS_TOKEN = "renren_sdk_config_prop_access_token"; private static final String RENREN_SDK_CONFIG_PROP_SESSION_KEY = "renren_sdk_config_prop_session_key"; private static final String RENREN_SDK_CONFIG_PROP_SESSION_SECRET = "renren_sdk_config_prop_session_secret"; private static final String RENREN_SDK_CONFIG_PROP_CREATE_TIME = "renren_sdk_config_prop_create_time"; private static final String RENREN_SDK_CONFIG_PROP_SESSION_CREATE_TIME = "renren_sdk_config_prop_session_create_time"; private static final String RENREN_SDK_CONFIG_PROP_EXPIRE_SECONDS = "renren_sdk_config_prop_expire_secends"; private static final String RENREN_SDK_CONFIG_PROP_USER_ID = "renren_sdk_config_prop_user_id"; private static final String KEY_ACCESS_TOKEN = "renren_token_manager_access_token"; private static final String KEY_SESSION_KEY = "renren_token_manager_session_key"; private static final String KEY_SESSION_SECRET = "renren_token_manager_session_secret"; private static final String KEY_UID = "renren_token_manager_user_id"; private static final String KEY_SESSION_KEY_EXPIRE_TIME = "renren_token_manager_session_key_expire_time"; private static final long ONE_HOUR = 1000 * 60 * 60; private Context context; private String accessToken = null; private String sessionKey; private String sessionSecret = null; /** * SessionKey 过期时间 */ private long expireTime = 0; /** * 保存当前登录用户的uid */ private long uid; AccessTokenManager(Context context) { this.context = context; compareWithConfig(); } public AccessTokenManager(Parcel in) { Bundle bundle = Bundle.CREATOR.createFromParcel(in); if (bundle != null) { accessToken = bundle.getString(KEY_ACCESS_TOKEN); sessionKey = bundle.getString(KEY_SESSION_KEY); sessionSecret = bundle.getString(KEY_SESSION_SECRET); expireTime = bundle.getLong(KEY_SESSION_KEY_EXPIRE_TIME); uid = bundle.getLong(KEY_UID); } compareWithConfig(); } String getAccessToken() { this.accessToken = this.restoreAccessToken(); return accessToken; } String getSessionKey() { if(sessionKey == null || sessionSecret == null) { initSessionKey(); } if(System.currentTimeMillis() > expireTime) { clearSessionParams(); } return this.sessionKey; } String getSessionSecret() { if(sessionKey == null || sessionSecret == null) { initSessionKey(); } if(System.currentTimeMillis() > expireTime) { clearSessionParams(); } return this.sessionSecret; } long getUid() { return this.uid; } public void setContext(Context context) { this.context = context; } /** * 返回当前session key是否有效 * @return * true - session key有效 * false - session key无效 */ public boolean isSessionKeyValid() { if(sessionKey != null && sessionSecret != null && System.currentTimeMillis() < expireTime) { return true; } //若当前sessionKey以及sessionSecret均为null,则 //尝试从SharedPreference中对sessionkey进行初始化 initSessionKey(); if(sessionKey != null && sessionSecret != null && System.currentTimeMillis() < expireTime) { return true; } return false; } /** * 更新accessToken;如果换取sessionKey出现错误抛出RenrenException。 * * @param accessToken */ void updateAccessToken(String accessToken) { this.updateAccessToken(accessToken, true); } void restoreSessionKey() { this.accessToken = this.restoreAccessToken(); //尝试从SharedPreference中初始化Session key以及Session Secret if(accessToken != null) { initSessionKey(); } try { initSessionKey(); //若没有session Key或者Session key已经过期 if(sessionKey == null || sessionSecret == null || expireTime < System.currentTimeMillis()) { this.exchangeSessionKey(accessToken); } } catch (Exception e) { e.printStackTrace(); this.clearPersistSession(); } } public boolean isSessionValid() { boolean flag = true ; this.accessToken = this.restoreAccessToken(); //尝试从SharedPreference中初始化Session key以及Session Secret if(accessToken != null) { initSessionKey(); } try { initSessionKey(); //若没有session Key或者Session key已经过期 if(sessionKey == null || sessionSecret == null || expireTime < System.currentTimeMillis()) { flag = false ; } } catch (Exception e) { e.printStackTrace(); this.clearPersistSession(); } return flag ; } /** * 检查当前的session信息与配置文件是否一直,若不一致,则对当前的sessionkey等进行初始化 * @return */ private void compareWithConfig() { if(context == null) { return; } // 对配置的变化进行监听,使得有多个Renren对象时,可以对权限信息保持一致 final SharedPreferences sp = context.getSharedPreferences( RENREN_SDK_CONFIG, Context.MODE_PRIVATE); sp.registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener() { @Override public void onSharedPreferenceChanged( SharedPreferences sharedPreferences, String key) { String sKey = sp.getString(RENREN_SDK_CONFIG_PROP_SESSION_KEY, null); String secret = sp.getString( RENREN_SDK_CONFIG_PROP_SESSION_SECRET, null); long userId = sp.getLong(RENREN_SDK_CONFIG_PROP_USER_ID, 0); if ((sessionKey != null && !sessionKey.equals(sKey)) || (sessionSecret != null && !sessionKey.equals(secret) || (sessionKey == null && sKey != null) || (sessionSecret == null && secret != null)) || (uid != userId)) { initSessionKey(); } } }); } void clearPersistSession() { Editor editor = context.getSharedPreferences(RENREN_SDK_CONFIG, Context.MODE_PRIVATE).edit(); editor.remove(RENREN_SDK_CONFIG_PROP_ACCESS_TOKEN); editor.remove(RENREN_SDK_CONFIG_PROP_CREATE_TIME); editor.remove(RENREN_SDK_CONFIG_PROP_SESSION_KEY); editor.remove(RENREN_SDK_CONFIG_PROP_SESSION_SECRET); editor.remove(RENREN_SDK_CONFIG_PROP_EXPIRE_SECONDS); editor.remove(RENREN_SDK_CONFIG_PROP_USER_ID); editor.commit(); this.accessToken = null; this.sessionKey = null; this.sessionSecret = null; this.expireTime = 0; this.uid = 0; } /** * 从SharedPreference中读入SessionKey */ private synchronized void initSessionKey() { SharedPreferences sp = context.getSharedPreferences(RENREN_SDK_CONFIG, Context.MODE_PRIVATE); sessionKey = sp.getString(RENREN_SDK_CONFIG_PROP_SESSION_KEY, null); sessionSecret = sp.getString(RENREN_SDK_CONFIG_PROP_SESSION_SECRET, null); uid = sp.getLong(RENREN_SDK_CONFIG_PROP_USER_ID, 0); long expires = sp.getLong(RENREN_SDK_CONFIG_PROP_EXPIRE_SECONDS, 0); long createTime = sp.getLong(RENREN_SDK_CONFIG_PROP_SESSION_CREATE_TIME, 0); long current = System.currentTimeMillis(); expireTime = createTime + expires; //sessioin key已过期, if(expireTime < current) { clearSessionParams(); sessionKey = null; sessionSecret = null; expireTime = 0; uid = 0; } } private void updateAccessToken(String accessToken, boolean isPersist) { if (accessToken == null || accessToken.length() < 1) { return; } this.accessToken = accessToken; try { initSessionKey(); //若没有session Key或者Session key已经过期 if(sessionKey == null || sessionSecret == null || expireTime < System.currentTimeMillis()) { this.exchangeSessionKey(accessToken); } } catch (Exception e) { e.printStackTrace(); this.clearPersistSession(); } if (isPersist) { this.storeAccessToken(accessToken); } else { this.clearPersistSession(); } } private void exchangeSessionKey(String accessToken) { if (accessToken == null || accessToken.length() < 1) { return; } Bundle params = new Bundle(); params.putString("oauth_token", accessToken); String sk = Util.openUrl(SESSION_KEY_URL, "POST", params); try { JSONObject obj = new JSONObject(sk); String error = obj.optString("error", null); if (error != null) { throw new RenrenError(obj.toString()); } sessionKey = obj.getJSONObject("renren_token").getString( "session_key"); sessionSecret = obj.getJSONObject("renren_token").getString( "session_secret"); // 获取当前登录用户的uid uid = obj.getJSONObject("user").getLong("id"); //服务器返回的过期时间单位为秒,故乘以1000 long expires = obj.getJSONObject("renren_token").getLong( "expires_in") * 1000; long current = System.currentTimeMillis(); expireTime = current + expires; // 存储当前获得的sessionKey, sessionSecret storeSessionParams(sessionKey, sessionSecret, current, expires, uid); Log.i(Util.LOG_TAG, "---login success sessionKey:" + sessionKey + " expires:" + expires + " sessionSecret:" + sessionSecret + " uid:" + uid); } catch (JSONException e) { throw new RuntimeException(e.getMessage(), e); } } /** * 存储accessToken, * @param accessToken */ private void storeAccessToken(String accessToken) { Editor editor = context.getSharedPreferences(RENREN_SDK_CONFIG, Context.MODE_PRIVATE).edit(); if (accessToken != null) { editor.putString(RENREN_SDK_CONFIG_PROP_ACCESS_TOKEN, accessToken); editor.putLong(RENREN_SDK_CONFIG_PROP_CREATE_TIME, System.currentTimeMillis()); } else { this.clearPersistSession(); } editor.commit(); } /** * 在SharedPreference中存储accessToken,sessionKey, sessionSecret以及过期时间 * @param accessToken * @param sessionKey * @param sessionSecret * @param expireTime Session key 的过期时间,单位为秒 * @param uid */ private void storeSessionParams(String sessionKey, String sessionSecret, long sessionCreateTime, long expires, long uid) { if (sessionKey == null || sessionSecret == null) { this.clearPersistSession(); return; } Editor editor = context.getSharedPreferences(RENREN_SDK_CONFIG, Context.MODE_PRIVATE).edit(); editor.putString(RENREN_SDK_CONFIG_PROP_SESSION_KEY, sessionKey); editor.putString(RENREN_SDK_CONFIG_PROP_SESSION_SECRET, sessionSecret); editor.putLong(RENREN_SDK_CONFIG_PROP_EXPIRE_SECONDS, expires); editor.putLong(RENREN_SDK_CONFIG_PROP_SESSION_CREATE_TIME, sessionCreateTime); editor.putLong(RENREN_SDK_CONFIG_PROP_USER_ID, uid); editor.commit(); } /** * 删除SharedPreference中存储的SessionKey信息 */ private void clearSessionParams() { Editor editor = context.getSharedPreferences(RENREN_SDK_CONFIG, Context.MODE_PRIVATE).edit(); editor.remove(RENREN_SDK_CONFIG_PROP_SESSION_KEY); editor.remove(RENREN_SDK_CONFIG_PROP_SESSION_SECRET); editor.remove(RENREN_SDK_CONFIG_PROP_EXPIRE_SECONDS); editor.remove(RENREN_SDK_CONFIG_PROP_SESSION_CREATE_TIME); editor.remove(RENREN_SDK_CONFIG_PROP_USER_ID); sessionKey = null; sessionSecret = null; expireTime = 0; uid = 0; editor.commit(); } private String restoreAccessToken() { SharedPreferences sp = context.getSharedPreferences(RENREN_SDK_CONFIG, Context.MODE_PRIVATE); String accessToken = sp.getString(RENREN_SDK_CONFIG_PROP_ACCESS_TOKEN, null); if (accessToken == null) { return null; } long createTime = sp.getLong(RENREN_SDK_CONFIG_PROP_CREATE_TIME, 0); long life = Long.parseLong(accessToken.split("\\.")[2]) * 1000; long currenct = System.currentTimeMillis(); if ((createTime + life) < (currenct - ONE_HOUR)) { this.clearPersistSession(); return null; } return accessToken; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { Bundle bundle = new Bundle(); if (accessToken != null) { bundle.putString(KEY_ACCESS_TOKEN, accessToken); } if (sessionKey != null) { bundle.putString(KEY_SESSION_KEY, sessionKey); } if (sessionSecret != null) { bundle.putString(KEY_SESSION_SECRET, sessionSecret); } if (expireTime != 0) { bundle.putLong(KEY_SESSION_KEY_EXPIRE_TIME, expireTime); } if (uid != 0) { bundle.putLong(KEY_UID, uid); } bundle.writeToParcel(dest, flags); } public static final Parcelable.Creator<AccessTokenManager> CREATOR = new Parcelable.Creator<AccessTokenManager>() { public AccessTokenManager createFromParcel(Parcel in) { return new AccessTokenManager(in); } public AccessTokenManager[] newArray(int size) { return new AccessTokenManager[size]; } }; }