不太了解Okta和Android.有没有人知道一个很好的教程,展示如何将Android应用程序连接到Okta框架.或者我实现SAML SSO实现,然后Okta与之相关联?任何代码示例都表示赞赏 - 特别是一个显示通用SSO的Android实现,如果存在这样的话.
Ste*_*ick 10
好的,这里有很多地方可以覆盖,还有一些我没做过的工作.但基本思想是在服务器端(我们使用.Net),我们使用"kentor"创建了一个SAML通信层.我没有使用它,但想法是软件通信客户端的身份提供商(IDP)为SSO(例如Okta).IDP客户端通常必须提供具有安全信息并最终提供URL的XML元数据,并向他们提供您的SSO xml元数据(抱歉,我没有在那部分工作!).
从那时起,它在Android方面非常直接.最重要的是,上述交互产生了一个URL,SSO客户端提供了您将在Android端使用的URL来创建webview,这将允许他们输入他们的登录信息进行验证.
我们有URL硬编码,因为我们专门为客户创建了一个白标产品(您将在Constants.SINGLE_SIGNON_URL下面看到),但是在客户通过SSO的组织代码后,没有什么可以阻止您将URL传回(我们正在工作)现在就这样).换句话说,您存储URL或根据哪个客户生成URL,然后在设备通过组织代码时返回该URL.该URL实际上是您的服务器,它重定向到SSO的IDP(Okta)登录页面.这是因为OKTA的响应需要转到您的服务器,最终将通过重定向发送回您的webview.我们使用cookie然后存储生成的用户名以允许正常的登录过程.可能有很多不同的方法,Okta甚至提供本机移动设备功能,但客户必须支持这一点.
这是一个图表,希望能够拼出一些高级的部分:
该代码仅涵盖上图中的1),2)和5).1)对WebView的调用非常明显.2)实际上是对Constants.SINGLE_SIGNON_URL服务器的调用,它应该重定向到IDP页面.当用户登录时,它会被发送回您的服务(SP)并重定向回您的WebView.同样,我们在cookie中存储了一些东西,以便继续正常登录.
一个关键是要意识到WebView shouldOverrideUrlLoading()被多次调用.忽略除发回服务器URL之外的所有内容,此时您需要提取所需的数据(在我们的例子中是服务器已验证的登录信息).这可以在电话中看到GlobalState.getInstance().currentUserName = getCookieValue("_username" ,cookies);
可能没有很好地解释这个问题(已经过了一个月左右!).以下是SSOActivity的一个示例,其中大部分工作已完成:
public class SSOActivity extends Activity {
WebView webView;
private Button mCancel;
private Button mReset;
/**
* Grabs the specified variables out of the list of cookies
*
* @param fieldName
* @param cookies
* @return
*/
public String getCookieValue(String fieldName, final String cookies){
String CookieValue = null;
String[] cookiessplit = cookies.split(";");
for (String str : cookiessplit ) {
if(str.contains(fieldName)) {
String[] value=str.split("=");
CookieValue = value[1];
break;
}
}
return CookieValue;
}
public void clearCookies() {
try {
android.webkit.CookieManager cookieManager = CookieManager.getInstance();
cookieManager.removeAllCookie();
}
catch (Exception ex)
{
Utilities.logException(ex);
Utilities.logError("SSOActivity", "clearCookies() : " + ex.getMessage() );
}
}
/**
* Cancels the SSO request in Webview
*
* @param view
*/
public void cancelSSOClick (View view) {
Utilities.logInfo("cancelSSOClick", "Cancel SSO click");
setResult(Activity.RESULT_CANCELED, null);
SSOActivity.this.finish();
}
/**
* Resets and deletes cookies and SSOUrl if one exists
*
* @param view
*/
public void resetSSOClick (View view) {
Utilities.logInfo("resetSSOClick", "Cancel SSO click");
setResult(Activity.RESULT_CANCELED, null);
clearCookies();
SSOActivity.this.finish();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setResult(Activity.RESULT_OK, null);
// Setup the web view. It will redirect to SSO site for login
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_sso);
mCancel = (Button)findViewById(R.id.cancelSSO);
mCancel.setTextColor(Color.WHITE);
mReset = (Button)findViewById(R.id.resetSSO);
mReset.setTextColor(Color.WHITE);
webView = (WebView) findViewById(R.id.ssoViewer);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setSupportZoom(false);
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading (WebView view, String url) {
try {
// If coming from our system, then we need to check the cookie for username password, for
// some SSO this might be different than the base url. Check for both
if (url.equals(Constants.getBaseUrl()) || url.equals(Constants.SSO_RETURN_URL)) {
CookieManager cookieManager = CookieManager.getInstance();
final String cookies = cookieManager.getCookie(url);
GlobalState.getInstance().currentUserName = getCookieValue("_username" ,cookies);
SSOActivity.this.finish();
return true;
}
}
catch (Exception ex) {
GlobalState.getInstance().currentUserName = "";
GlobalState.getInstance().currentPassword = "";
setResult(Activity.RESULT_CANCELED, null);
SSOActivity.this.finish();
}
return false;
}
});
try {
webView.loadUrl(Constants.SINGLE_SIGNON_URL);
}
catch (Exception ex) {
Utilities.logException(ex);
Utilities.logError("SSOActivity", "onCreate(), webView.loadUrl(ssoUrl) : " + ex.getMessage() );
}
}
}
Run Code Online (Sandbox Code Playgroud)
以下是支持Activity的XML示例:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/ssoViewerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/button_layout"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="wrap_content"
android:gravity="center|bottom"
android:layout_alignParentBottom="true">
<Button
android:id="@+id/cancelSSO"
android:layout_marginTop="16dp"
android:layout_width="125dp"
android:layout_height="55dp"
android:layout_margin="5dp"
android:onClick="cancelSSOClick"
android:text="Cancel Login"
android:background="@drawable/button_login" />
<Button
android:id="@+id/resetSSO"
android:layout_marginTop="16dp"
android:layout_width="125dp"
android:layout_height="55dp"
android:layout_margin="5dp"
android:onClick="resetSSOClick"
android:text="Reset SSO"
android:background="@drawable/button_login"/>
</LinearLayout>
<WebView
android:id="@+id/ssoViewer"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="@id/button_layout" />
</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)
调用它在代码中的其他位置如下所示:
Intent viewIntent = new Intent(getActivity(), SSOActivity.class);
(getActivity()).startActivityForResult(viewIntent, Constants.SINGLE_SIGN_ON);
Run Code Online (Sandbox Code Playgroud)
最后你应该看到:
希望这可以帮助!
| 归档时间: |
|
| 查看次数: |
1049 次 |
| 最近记录: |