当前位置: 代码迷 >> Android >> Android仿众人客户端(v5.7.1)——Auth授权认证(整理流程,重构代码)
  详细解决方案

Android仿众人客户端(v5.7.1)——Auth授权认证(整理流程,重构代码)

热度:7   发布时间:2016-05-01 10:58:44.0
Android仿人人客户端(v5.7.1)——Auth授权认证(整理流程,重构代码)

转载请标明出处:http://blog.csdn.net/android_ls/article/details/8748901      

 声明:关于仿人人项目,我是边看人人官方提供的API,边思考,整理好思路,就开始编写代码。有些地方考虑的不是很全面,大家在阅读的时候,对某些细节的处理,若有什么好的处理方式,欢迎交流。(请注意交流时的用词,文明沟通,谢谢。)

      人人授权认证已聊了两篇了,这篇重点是整理思路和重构代码(项目开发过程中开发人员经常干的事)。好了不废话,下面开始聊今天的内容。

一、人人Auth授权认证流程图:

二、重构代码:

       1、再次访问授权页出现的空白页,如下图:

        解决方法,修改WebView组件的请求重定向方法,处理代码如下:

  mWebView.setWebViewClient(new WebViewClient() {            public boolean shouldOverrideUrlLoading(WebView webView, String url) {                Log.i(TAG, "shouldOverrideUrlLoading() Redirect URL = " + url);                if (url.startsWith(Constant.DEFAULT_REDIRECT_URI + "#error=login_denied")) {                    AuthActivity.this.onBackPressed();                } else if(url.startsWith(Constant.DEFAULT_REDIRECT_URI + "#access_token")) {                    String accessToken = url.substring(url.indexOf("=")+1, url.indexOf("&"));                    Log.i(TAG, "accessToken = " + accessToken);                                        // 人人Demo LOG打印: 195789|6.7faefec2274182195287028d00323781.2592000.1367118000-461345584                                        // 服务器端返回: 195789%7C6.7faefec2274182195287028d00323781.2592000.1367118000-461345584                    accessToken = accessToken.replace("%7C", "|");                    Log.i(TAG, "Success obtain accessToken = " + accessToken);                                        // 存储AccessToken                    mAuthTokenManager.storeAccessToken(accessToken);                                        exchangeSessionKey(accessToken);                } else {                    webView.loadUrl(url);                }                               return true;            }            public void onReceivedSslError(WebView view, SslErrorHandler handler, android.net.http.SslError errorCode) {                // 在默认情况下,通过loadUrl(String url)方法,可以顺利load。                // 但是,当load有ssl层的https页面时,如果这个网站的安全证书在Android无法得到认证,WebView就会变成一个空白页,                // 而并不会像PC浏览器中那样跳出一个风险提示框。因此,我们必须针对这种情况进行处理。(这个证书限于2.1版本以上的Android 系统才可以)                                // 默认的处理方式,WebView变成空白页                // handler.cancel();                                 // 接受证书                   handler.proceed();            }            @Override            public void onReceivedError(WebView view, int errorCode,                    String description, String failingUrl) {                super.onReceivedError(view, errorCode, description, failingUrl);                AuthActivity.this.onBackPressed();            }            public void onPageStarted(WebView view, String url, Bitmap favicon) {                Log.i(TAG, "onPageStarted() URL = " + url);                                // super.onPageStarted(view, url, favicon);            }            public void onPageFinished(WebView view, String url) {                                Log.i(TAG, "onPageFinished() URL = " + url);                                // super.onPageFinished(view, url);            }        });


      2、将有关认证授权信息提取放到认证信息管理类中,代码如下:

package com.everyone.android;import android.content.Context;import android.content.SharedPreferences;import android.content.SharedPreferences.Editor;import com.everyone.android.entity.Authorization;/** * 功能描述:认证授权信息管理类 * @author android_ls * */public final class AuthTokenManager {    private Context mContext;    private SharedPreferences mSharedPreferences;        public AuthTokenManager(Context context){        this.mContext = context;        mSharedPreferences = mContext.getSharedPreferences("auth_config", Context.MODE_PRIVATE);    }        /**     * 获取accessToken     * @return     */    public String getAccessToken() {        String accessToken = mSharedPreferences.getString("oauth_token", null);        if (accessToken == null) {            return null;        }                long createTime = mSharedPreferences.getLong("create_oauth_token_time", 0);        long life = Long.parseLong(accessToken.split("\\.")[2]) * 1000;        long currenct = System.currentTimeMillis();        long oneHour = 1000 * 60 * 60;        if ((createTime + life) < (currenct - oneHour)) {            Editor editor = mSharedPreferences.edit();            editor.clear();            editor.commit();            return null;        }        return accessToken;    }        /**     * 存储accessToken,     * @param accessToken     */    public void storeAccessToken(String accessToken) {        Editor editor = mSharedPreferences.edit();        if (accessToken != null) {            editor.putString("oauth_token", accessToken);            editor.putLong("create_oauth_token_time", System.currentTimeMillis());        } else {            editor.clear();        }        editor.commit();    }        /**     * 在本地存储Authorization     * @param auth     */    public void save(Authorization auth){        Editor editor = mSharedPreferences.edit();        editor.putString("session_key", auth.getSessionKey());        editor.putString("session_secret", auth.getSessionSecret());        editor.putLong("expires_in", auth.getExpiresIn());        editor.putLong("create_session_time", auth.getCreateSessionTime());        // editor.putString("oauth_token", auth.getOauthToken());        editor.putLong("userId", auth.getUserId());        editor.commit();    }        /**     * 从SharedPreference中读入SessionKey     */    private Authorization getAuthBySharedPre() {        // String oauthToken = mSharedPreferences.getString("oauth_token", null);        String sessionKey = mSharedPreferences.getString("session_key", null);        String sessionSecret = mSharedPreferences.getString("session_secret", null);        long userId = mSharedPreferences.getLong("userId", 0);        long expires = mSharedPreferences.getLong("expires_in", 0);         long createTime = mSharedPreferences.getLong("create_session_time", 0);        long expireTime = createTime + expires;                Authorization auth = new Authorization();        // auth.setOauthToken(oauthToken);        auth.setSessionKey(sessionKey);        auth.setSessionSecret(sessionSecret);        auth.setCreateSessionTime(createTime);        auth.setExpiresIn(expireTime);        auth.setUserId(userId);        return auth;    }        /**     * 检测当前session是否有效     * @return      *      true - session 有效     *      false - session 无效     */    public boolean isSessionValid() {        Authorization auth = getAuthBySharedPre();        long current = System.currentTimeMillis();        if(auth.getSessionKey() != null && auth.getSessionSecret() != null                 && current < auth.getExpiresIn()) {           return true;        }                // sessioin 已过期,删除SharedPreference中存储的SessionKey信息        Editor editor = mSharedPreferences.edit();        editor.clear();        editor.commit();        return false;    }    }

3、将服务器端返回的授权认证JSON字符串的解析工作提取

package com.everyone.android.parse;import org.json.JSONException;import org.json.JSONObject;import com.everyone.android.entity.Authorization;/** * 功能描述:负责解析Auth认证的JSON字符串 * @author android_ls * */public final class AuthParse {    public static Authorization getAuth(String json) throws JSONException {        JSONObject jsonObject = new JSONObject(json);                JSONObject jsonRenrenToken = jsonObject.getJSONObject("renren_token");        String sessionKey = jsonRenrenToken.getString("session_key");        String sessionSecret = jsonRenrenToken.getString("session_secret");        long expiresIn = jsonRenrenToken.getLong("expires_in");                String oauthToken = jsonObject.getString("oauth_token");        long userId = jsonObject.getJSONObject("user").getLong("id");                // 对Session过期时间进行处理,  Session过期时间 = 系统当前的时间 + 服务器端返回的Session过期时间。        long createSessionTime = System.currentTimeMillis();        expiresIn = createSessionTime + expiresIn*1000; // 服务器端返回的Session过期时间单位为秒,因此需要乘以1000                Authorization auth = new Authorization();        auth.setOauthToken(oauthToken);        auth.setSessionKey(sessionKey);        auth.setSessionSecret(sessionSecret);        auth.setCreateSessionTime(createSessionTime);        auth.setExpiresIn(expiresIn);        auth.setUserId(userId);                return auth;    }    }

4、授权认证界面的处理:

  /**     * 通过accessToken换取session_key、session_secret和userId     * @param accessToken     */    private void exchangeSessionKey(String accessToken) {        if (accessToken == null || accessToken.length() < 1) {            return;        }                Map<String, String> parameter = new HashMap<String, String>();        parameter.put("oauth_token", accessToken);        AsyncBaseRequest asyncRequest = new AsyncHttpPost(Constant.SESSION_KEY_URL, parameter,                new ParseCallback (){                    @Override                    public Authorization parse(String json) throws JSONException {                        Log.i(TAG, "result = " + json);                        if(!TextUtils.isEmpty(json)){                                                        // 服务器端返回的JSON字符串:                           /*{                               "renren_token":                               {                                   "session_secret":"52e95c7b02abb0a80a4a80116438063a",                                   "expires_in":2595334,                                   "session_key":"6.8fed55fdfd5c027c2ecb0ac50859f97c.2592000.1367121600-461345584"                               },                               "oauth_token":"195789|6.8fed55fdfd5c027c2ecb0ac50859f97c.2592000.1367121600-461345584",                               "user":                               {                                   "id":461345584                               }                            }*/                            // 解析JSON                            Authorization auth = AuthParse.getAuth(json);                            Log.e(TAG, "auth = " + auth.toString());                            return auth;                        }                        return null;                    }                    },         new  ResultCallback(){            @Override            public void onSuccess(final Object result) {                if (!(result instanceof Authorization)) {                   Log.e(TAG, "网络请求返回值解析后不是Authorization类型");                   return;                }                                // 本地存储Authorization授权认证数据                mAuthTokenManager.save((Authorization)result);                mHandler.post(new Runnable() {                                        @Override                    public void run() {                        if (mWebView != null) {                            mWebView.stopLoading();                        }                                                Intent intent = new Intent(AuthActivity.this, EveryoneActivity.class);                        AuthActivity.this.startActivity(intent);                             AuthActivity.this.finish();                    }                });            }            @Override            public void onFail(int errorCode) {                Log.e(TAG, "网络请求返回的errorCode = " + errorCode);                            }                    });                mDefaultThreadPool.execute(asyncRequest);        mAsyncRequests.add(asyncRequest);    }

5、导引界面添加的处理:

 // 检测accessToken是否有效            String accessToken = mAuthTokenManager.getAccessToken();            LogUtil.i(TAG, "accessToken = " + accessToken);            Intent intent = new Intent();            if (accessToken == null) {                intent.setClass(this, AuthActivity.class);                startActivity(intent);                return;            }            // 检测Session是否有效            if (mAuthTokenManager.isSessionValid()) {                intent.setClass(this, EveryoneActivity.class);                startActivity(intent);                finish();            } else {                // accessToken有效,Session失效                exchangeSessionKey(accessToken);            }

注:当accessToken有效,Session失效时的处理,与授权界面的通过accessToken换取session_key、session_secret和userId基本一致,就不贴代码了。

6、Auth信息实体类代码:

package com.everyone.android.entity;/** * 功能描述:Auth信息实体类 * @author android_ls * */public class Authorization {    private String oauthToken; // accessToken    private long userId; // 当前登录用户的uid    private String sessionKey; // Session key    private String sessionSecret; // Session Secret    private long expiresIn; // Session 过期时间    private long createSessionTime; // 创建时间(从服务器端获取到时的本地时间)    public String getOauthToken() {        return oauthToken;    }    public void setOauthToken(String oauthToken) {        this.oauthToken = oauthToken;    }    public long getUserId() {        return userId;    }    public void setUserId(long userId) {        this.userId = userId;    }    public String getSessionKey() {        return sessionKey;    }    public void setSessionKey(String sessionKey) {        this.sessionKey = sessionKey;    }    public String getSessionSecret() {        return sessionSecret;    }    public void setSessionSecret(String sessionSecret) {        this.sessionSecret = sessionSecret;    }    public long getExpiresIn() {        return expiresIn;    }    public void setExpiresIn(long expiresIn) {        this.expiresIn = expiresIn;    }    public long getCreateSessionTime() {        return createSessionTime;    }    public void setCreateSessionTime(long createSessionTime) {        this.createSessionTime = createSessionTime;    }    public String toString() {        StringBuilder authResult = new StringBuilder();        authResult.append(" oauth_token = ").append(oauthToken);        authResult.append("\n session_key = ").append(sessionKey);        authResult.append("\n session_secret = ").append(sessionSecret);        authResult.append("\n expires_in = ").append(expiresIn);        authResult.append("\n userId = ").append(userId);        return authResult.toString();    }}


有关人人Auth认证的到这里就聊完了。

 

  相关解决方案