学习新浪微博开发的OAuth2.0登陆协议(阶段一)

OAuth2.0是一种较安全的登陆第三方应用的协议,它有效的避免用户密码和账户直接登陆第三方应用,因此这种协议的安全性比较高,现在很多应用都采用了这种协议来开放API接口,例如facebook,新浪微博等重要应用,对于OAuth2.0协议登陆与传统登陆,我参考了http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html博客,在这里画了个流程图可以比较:
学习新浪微博开发的OAuth2.0登陆协议(阶段一)_第1张图片
接下来我就用授权码的模式来实现新浪微博的OAuth2.0登陆协议,准备的工作就是你要去新浪那里申请client_id,client_secret,redirect_uri等这些数据,申请完,就可以参考其文档来实现自己的OAuth2.0登陆协议,只不过这里与新浪微博的SDK实现SSO和Web登陆模式不一样(这里涉及到应用钥匙和应用包名,其如何实现,本人没看懂其反编译的源码,故就不清楚了),所以我决定自己参考其新浪微博文档学习其OAuth2.0协议的授权码登陆模式。
这是我整个学习过程中项目阶段一的开发流程图:
学习新浪微博开发的OAuth2.0登陆协议(阶段一)_第2张图片
这里主要讲OAuth2.0协议的实现,所以主要贴出OAuth2.0核心代码,其他的代码就不贴出来了。
实现新浪微博OAuth2.0登陆协议核心代码:

/** * Author:beyondboy * Gmail:[email protected] * Date: 2015-04-30 * Time: 11:15 */
/** * 这里要导入第三方AsyncHttpClient包 * 主要用来异步发送oauth各种请求 */
public class OAuthRestUtils {
    /**URL的基地址*/
    private static final  String BASE_URL="https://api.weibo.com/oauth2/";
    private static AsyncHttpClient sClient=new AsyncHttpClient();
    /** * 发送get的请求 * @param url 发送URL的地址 * @param params URL的参数设置 * @param responseHandler 响应服务器处理对象 */
    public static void get(String url, RequestParams params, AsyncHttpResponseHandler responseHandler)
    {
        sClient.get(getAbsoluteUrl(url), params, responseHandler);
    }
    /** * 发送post的请求 * @param url 发送URL的地址 * @param params URL的参数设置 * @param responseHandler 响应服务器处理对象 */
    public static void post(String url, RequestParams params, AsyncHttpResponseHandler responseHandler)
    {
        sClient.post(getAbsoluteUrl(url), params, responseHandler);
    }
    /**返回URL的绝对地址*/
    private static String getAbsoluteUrl(String relativeUrl)
    {
        return BASE_URL + relativeUrl;
    }
}


/** * 储存请求各种参数的常量 */
public class Constants {
    //请求参数UR:Lhttps://api.weibo.com/oauth2/authorize?client_id="你的Id"&redirect_uri="你的回调地址"&response_type=code(注意参数顺序要一致啊)
    /**开发者的id*/
    public static final String APP_KEY="你的Id";
    /**开发者网站的回调地址*/
    public static final String REDIRECT_URL="你的回调地址";
    /**应用密匙*/
    public static final String APP_SECRET="你的应用密匙";
    /**授权页面引用地址*/
    public static final String URL="https://api.weibo.com/oauth2/authorize?client_id="+APP_KEY+"&redirect_uri="+REDIRECT_URL+"&response_type=code";
}


/** * 引用用户到授权页面并且 * 申请请求access_token令牌 */
public class OAuthActivity extends Activity {
    private static final String TAG = "OAuthActivity";
    /**储存OAuth2.0重要信息*/
    private SharedPreferences mPreferences;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        mPreferences =getSharedPreferences("OAuth", Context.MODE_PRIVATE);
        Log.i(TAG, "oncreate");
        LinearLayout linearLayout=new LinearLayout(this);
        WebView webView=new WebView(this);
        linearLayout.addView(webView, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT));
        setContentView(linearLayout);
        String url= Constants.URL;
        WebSettings webSettings= webView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webSettings.setSupportZoom(true);
        webView.requestFocus();
        Log.i(TAG, "开始加载");
        //发送URL地址先请求获得code
        webView.loadUrl(url);
        WebViewClient client=new WebViewClient()
        {
             /** * 页面加载时会回调该方法,如果用户同意就会成功获取code * 然后发送一个异步的post请求获取access_token * 若成功获取access_token信息,则保存所有重要信息 * 并跳转到主界面 * @param view 显现界面视图 * @param url 加载网址 * @param favicon 网址的相关图标 */
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon)
            {
                Log.i(TAG,"页面开始加载");
                Log.i(TAG,url);
                if(url.contains("code="))
                {
                    //服务器返回数据
                    //https://api.weibo.com/oauth2/default.html?code=6d6feeac282a3438880a5d95d95c115c
                    String code=url.split("=")[1];
                    //请求access_token的URL:
                    //https://api.weibo.com/oauth2/access_token?
                    // client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET
                    // &grant_type=authorization_code&redirect_uri=YOUR_REGISTERED_REDIRECT_URI
                    // &code=CODE
                    //设置请求参数
                    RequestParams params=new RequestParams();
                    params.put("client_id",Constants.APP_KEY);
                    params.put("client_secret",Constants.APP_SECRET);
                    params.put("grant_type","authorization_code");
                    params.put("redirect_uri", Constants.REDIRECT_URL);
                    params.put("code", code);
                    //发送异步post请求access_token令牌,并保存的OAthu的
                    // client_id和client_secret和access_token等重要信息
                    OAuthRestUtils.post("access_token",params, new AsyncHttpResponseHandler()
                    {
                        @SuppressLint("CommitPrefEdits")
                        @Override
                        public void onSuccess(int statusCode, Header[] headers, byte[] responseBody)
                        {
                            //服务器返回数据
                            //{"access_token":"这里会是一串字符",
                            // "remind_in":"157679999",
                            // "expires_in":157679999,
                            // "uid":"3779157603"}
                            Log.i(TAG, "获取access_token成功");
                            String data=new String(responseBody);
                            try
                            {
                                JSONObject object=new JSONObject(data);
                                (mPreferences.edit()).clear();
                                //保存重要的各种数据信息
                                saveInfo(object);
                                Intent intent=new Intent(OAuthActivity.this, MainActivity.class);
                                startActivity(intent);//todo 这里还有些没有完成
                                OAuthActivity.this.finish();

                            } catch (JSONException e)
                            {
                                Log.i(TAG,"json解析异常");
                                e.printStackTrace();
                            }
                        }
                        @Override
                        public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error)
                        {
                            //todo 这里申请access_token令牌失败方法暂未处理
                            Log.i(TAG,"获取access_token失败");
                            OAuthActivity.this.finish();
                        }
                    });
                }
            }
            /** * 保存的OAthu的client_id和client_secret和access_token等重要信息 */
            public  void saveInfo(JSONObject object)
            {
                try
                {
                    SharedPreferences.Editor editor= mPreferences.edit();
                    editor.putString("access_token",object.getString("access_token"));
                    editor.putString("remind_in",object.getString("remind_in"));
                    editor.putString("expires_in",object.getString("expires_in"));
                    editor.putString("client_id",Constants.APP_KEY);
                    editor.putString("redirect_uri",Constants.REDIRECT_URL);
                    editor.putString("client_secret",Constants.APP_SECRET);
                    editor.apply();
                } catch (JSONException e)
                {
                    Log.i(TAG,"存储失败");
                    e.printStackTrace();
                }
            }
        };
        webView.setWebViewClient(client);
    }
}

运行结果:

  • 授权页面
    学习新浪微博开发的OAuth2.0登陆协议(阶段一)_第3张图片
  • 同意授权返回输出结果:
    这里写图片描述
  • 第二次登陆结果的打印数据:

    注意,前面两部是针对第一次登陆该应用,或者access_token过期的时候启动的,上面同意授权页面我没有打出服务器返回的数据,这里大家可以自己去把它打印出来看看,保存好这些数据,进入以第二次登陆时候就可以直接利用其保存的数据而不用再进行授权了。
    注意事项:
  • URL的参数顺序要与官网文档一致
  • access_token请求要发送post请求,而不能用get的请求(对于get和post请求的区别,自己上百度搜索)
    OAuth2.0协议安全的扩张学习,可以参考下面博客:
    http://drops.wooyun.org/papers/598

你可能感兴趣的:(oauth2,新浪微博OAuth2)