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