package com.weibo.sdk.android.sso; import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.pm.Signature; import android.os.IBinder; import android.os.RemoteException; import android.text.TextUtils; import android.util.Log; import com.sina.sso.RemoteSSO; import com.weibo.sdk.android.Oauth2AccessToken; import com.weibo.sdk.android.Weibo; import com.weibo.sdk.android.WeiboAuthListener; import com.weibo.sdk.android.WeiboDialogError; import com.weibo.sdk.android.util.Utility; /** * 该类用于处理sso 认证功能,通过sso,无需输入用户名、密码即可以通过微博账号访问经过授权的第三方应用,\r\n * 使用SSO登录前,请检查手机上是否已经安装新浪微博客户端,目前仅3.0.0及以上微博客户端版本支持SSO; * 如果未安装,将自动转为Oauth2.0进行认证 * * @author xiaowei6@staff.sina.com.cn * */ public class SsoHandler { private ServiceConnection conn = null; private static final int DEFAULT_AUTH_ACTIVITY_CODE = 32973; private static final String WEIBO_SIGNATURE = "30820295308201fea00302010202044b4ef1bf300d" + "06092a864886f70d010105050030818d310b300906035504061302434e3110300e0603550408130" + "74265694a696e673110300e060355040713074265694a696e67312c302a060355040a132353696e" + "612e436f6d20546563686e6f6c6f677920284368696e612920436f2e204c7464312c302a0603550" + "40b132353696e612e436f6d20546563686e6f6c6f677920284368696e612920436f2e204c746430" + "20170d3130303131343130323831355a180f32303630303130323130323831355a30818d310b300" + "906035504061302434e3110300e060355040813074265694a696e673110300e0603550407130742" + "65694a696e67312c302a060355040a132353696e612e436f6d20546563686e6f6c6f67792028436" + "8696e612920436f2e204c7464312c302a060355040b132353696e612e436f6d20546563686e6f6c" + "6f677920284368696e612920436f2e204c746430819f300d06092a864886f70d010101050003818" + "d00308189028181009d367115bc206c86c237bb56c8e9033111889b5691f051b28d1aa8e42b66b7" + "413657635b44786ea7e85d451a12a82a331fced99c48717922170b7fc9bc1040753c0d38b4cf2b2" + "2094b1df7c55705b0989441e75913a1a8bd2bc591aa729a1013c277c01c98cbec7da5ad7778b2fa" + "d62b85ac29ca28ced588638c98d6b7df5a130203010001300d06092a864886f70d0101050500038" + "181000ad4b4c4dec800bd8fd2991adfd70676fce8ba9692ae50475f60ec468d1b758a665e961a3a" + "edbece9fd4d7ce9295cd83f5f19dc441a065689d9820faedbb7c4a4c4635f5ba1293f6da4b72ed3" + "2fb8795f736a20c95cda776402099054fccefb4a1a558664ab8d637288feceba9508aa907fc1fe2" + "b1ae5a0dec954ed831c0bea4"; // private String[] mAuthPermissions; private int mAuthActivityCode; private static String ssoPackageName = "";// "com.sina.weibo"; private static String ssoActivityName = "";// "com.sina.weibo.MainTabActivity"; private WeiboAuthListener mAuthDialogListener; private Oauth2AccessToken mAccessToken = null; private Activity mAuthActivity; private Weibo mWeibo; public SsoHandler(Activity activity,Weibo weibo) { mAuthActivity = activity; mWeibo=weibo; Weibo.isWifi=Utility.isWifi(activity); conn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { mWeibo.startAuthDialog(mAuthActivity, mAuthDialogListener); } @Override public void onServiceConnected(ComponentName name, IBinder service) { RemoteSSO remoteSSOservice = RemoteSSO.Stub .asInterface(service); try { ssoPackageName = remoteSSOservice.getPackageName(); ssoActivityName = remoteSSOservice.getActivityName(); boolean singleSignOnStarted = startSingleSignOn( mAuthActivity, Weibo.app_key, new String[]{}, mAuthActivityCode); if (!singleSignOnStarted) { // startDialogAuth(mAuthActivity, new String[]{}); mWeibo.startAuthDialog(mAuthActivity, mAuthDialogListener); } } catch (RemoteException e) { e.printStackTrace(); } } }; } /** * 进行sso认证 * * @param activity 发起认证的Activity * * @param listener 用于接收认证信息的监听者 */ public void authorize( final WeiboAuthListener listener) { authorize( DEFAULT_AUTH_ACTIVITY_CODE, listener); } private void authorize( int activityCode, final WeiboAuthListener listener) { mAuthActivityCode = activityCode; boolean bindSucced = false; mAuthDialogListener = listener; // Prefer single sign-on, where available. bindSucced = bindRemoteSSOService(mAuthActivity); // Otherwise fall back to traditional dialog. if (!bindSucced) { if(mWeibo!=null){ mWeibo.startAuthDialog(mAuthActivity, mAuthDialogListener); } } } private boolean bindRemoteSSOService(Activity activity) { Context context = activity.getApplicationContext(); Intent intent = new Intent("com.sina.weibo.remotessoservice"); return context.bindService(intent, conn, Context.BIND_AUTO_CREATE); } private boolean startSingleSignOn(Activity activity, String applicationId, String[] permissions, int activityCode) { boolean didSucceed = true; Intent intent = new Intent(); intent.setClassName(ssoPackageName, ssoActivityName); intent.putExtra("appKey", applicationId);// applicationId //"2745207810" intent.putExtra("redirectUri", Weibo.redirecturl); if (permissions.length > 0) { intent.putExtra("scope", TextUtils.join(",", permissions)); } // validate Signature if (!validateAppSignatureForIntent(activity, intent)) { return false; } try { activity.startActivityForResult(intent, activityCode); } catch (ActivityNotFoundException e) { didSucceed = false; } activity.getApplication().unbindService(conn); return didSucceed; } private boolean validateAppSignatureForIntent(Activity activity, Intent intent) { ResolveInfo resolveInfo = activity.getPackageManager().resolveActivity( intent, 0); if (resolveInfo == null) { return false; } String packageName = resolveInfo.activityInfo.packageName; try { PackageInfo packageInfo = activity.getPackageManager() .getPackageInfo(packageName, PackageManager.GET_SIGNATURES); for (Signature signature : packageInfo.signatures) { if (WEIBO_SIGNATURE.equals(signature.toCharsString())) { return true; } } } catch (NameNotFoundException e) { return false; } return false; } /** * 重要:发起认证的Activity必须重写onActivityResult, 这个方法必须在onActivityResult 方法内调用, * 例如:<br/> * * @Override * protected void onActivityResult(int requestCode, int resultCode, Intent data) {<br/> * super.onActivityResult(requestCode, resultCode, data);<br/> * if(mSsoHandler!=null){<br/> * mSsoHandler.authorizeCallBack(requestCode, resultCode, data);<br/> * }<br/> * } */ public void authorizeCallBack(int requestCode, int resultCode, Intent data) { if (requestCode == mAuthActivityCode) { // Successfully redirected. if (resultCode == Activity.RESULT_OK) { // Check OAuth 2.0/2.10 error code. String error = data.getStringExtra("error"); if (error == null) { error = data.getStringExtra("error_type"); } // error occurred. if (error != null) { if (error.equals("access_denied") || error.equals("OAuthAccessDeniedException")) { Log.d("Weibo-authorize", "Login canceled by user."); mAuthDialogListener.onCancel(); } else { String description = data .getStringExtra("error_description"); if (description != null) { error = error + ":" + description; } Log.d("Weibo-authorize", "Login failed: " + error); mAuthDialogListener.onError(new WeiboDialogError(error, resultCode, description)); } // No errors. } else { if (null == mAccessToken) { mAccessToken = new Oauth2AccessToken(); } mAccessToken.setToken(data.getStringExtra(Weibo.KEY_TOKEN)); mAccessToken.setExpiresIn(data .getStringExtra(Weibo.KEY_EXPIRES)); mAccessToken.setRefreshToken(data .getStringExtra(Weibo.KEY_REFRESHTOKEN)); if (mAccessToken.isSessionValid() == 1) { Log.d("Weibo-authorize", "Login Success! access_token=" + mAccessToken.getToken() + " expires=" + mAccessToken.getExpiresTime() + "refresh_token=" + mAccessToken.getRefreshToken()); mAuthDialogListener.onComplete(data.getExtras()); } else { Log.d("Weibo-authorize", "Failed to receive access token by SSO"); // startDialogAuth(mAuthActivity, mAuthPermissions); mWeibo.startAuthDialog(mAuthActivity, mAuthDialogListener); } } // An error occurred before we could be redirected. } else if (resultCode == Activity.RESULT_CANCELED) { // An Android error occured. if (data != null) { Log.d("Weibo-authorize", "Login failed: " + data.getStringExtra("error")); mAuthDialogListener.onError(new WeiboDialogError(data .getStringExtra("error"), data.getIntExtra( "error_code", -1), data .getStringExtra("failing_url"))); // User pressed the 'back' button. } else { Log.d("Weibo-authorize", "Login canceled by user."); mAuthDialogListener.onCancel(); } } } } }