场景简介
https帐号认证,ldap用户认证以及radius认证是常用的外部认证方式,三种方式在移动端的集成方式大同小异,调用接口基本与用户名/密码一致,原理上也都是联动外部第三方服务器做认证,只是在调用认证接口传递认证参数上有点区别。
前置步骤
流程图
集成步骤
1、初始化SDK
注意:SDK接口都需要在SDK初始化后才能调用,否则会抛出异常。
初始化SDK主要是完成SDK核心功能配置的初始化,放到Application的attachBaseContext中初始化。
示例代码如下:
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
initSDK(base);
}
/**
* 初始化SangforSDK
*
* @param context
*/
private void initSDK(Context context) {
Map<SFSDKExtras, String> extra = new HashMap<>();
int sdkFlags = SFSDKFlags.FLAGS_HOST_APPLICATION;
sdkFlags |= SFSDKFlags.FLAGS_VPN_MODE_TCP;
SFUemSDK.getInstance().initSDK(context, SFSDKMode.MODE_VPN_SANDBOX, sdkFlags, extra);
}
注意
SFSDKMode.MODE_VPN_SANDBOX: 该模式是启用vpn代理功能,和启用终端安全沙箱功能(水印,分享隔离,剪切板隔离等等安全功能); 只有当集成SDK的APP在应用中心授权给用户, 用户才可以使用集成SDK的APP接入使用, 并且占用并发授权和UEM移动版授权;
SFSDKMode.MODE_VPN: 该模式表示只是启用vpn代理功能,不启用终端安全沙箱功能(水印,分享隔离,剪切板隔等等安全功能); 无论集成SDK的APP是否在应用中心授权给用户, 用户都可以使用集成SDK的APP接入使用, 并且仅占用并发授权;
沙箱文件加密功能说明:
沙箱功能中的文件加密功能是指,如果终端(手机)开启文件加密,app中需要落盘的数据会自动被加密然后重定向,以保证数据在手机存储里面的安全;
集成步骤上只需要在上面初始化的时候增加flag:SFSDKFlags.FLAGS_ENABLE_FILE_ISOLATION 并设置SDKMode为SFSDKMode.MODE_VPN_SANDBOX
示例代码如下:
/**
* 初始化SangforSDK
*
* @param context
*/
private void initSDK(Context context) {
Map<SFSDKExtras, String> extra = new HashMap<>();
int sdkFlags = SFSDKFlags.FLAGS_HOST_APPLICATION;
sdkFlags |= SFSDKFlags.FLAGS_VPN_MODE_TCP;
//开启文件加密功能
sdkFlags |= SFSDKFlags.FLAGS_ENABLE_FILE_ISOLATION;
SFUemSDK.getInstance().initSDK(context, SFSDKMode.MODE_VPN_SANDBOX, sdkFlags, extra);
}
2、设置认证回调
aTrust身份认证属于通过网络耗时操作,SDK实现时是通过代理异步回调来获取认证结果。请务必在使用认证接口前,按要求实现并注册认证结果回调。
示例代码如下:
public class PrimaryExternalAuthActivity extends AppCompatActivity implements SFAuthResultListener, View.OnClickListener {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_psw);
/**
* 设置认证回调,认证结果在SFAuthResultListener的onAuthSuccess、onAuthFailed、onAuthProgress中返回
* 如果不设置,将接收不到认证结果回调
*/
SFUemSDK.getInstance().setAuthResultListener(this);
}
@Override
protected void onPause() {
super.onPause();
//只有走回收流程的时候的那种onPause,isFinishing才为true
if (isFinishing()) {
//取消认证回调
SFLogN.info(TAG,"SFUemSDK setAuthResultListener null");
/**
* 注意: 清除回调建议放到onPause()方法而不是onDestroy()中,
* 避免出现onDestroy()在onCreate()之后执行,onCreate注册的认证回调被onDestory清空的问题
*/
SFUemSDK.getInstance().setAuthResultListener(null);
}
}
}
3、外部主认证
示例代码如下:
String url = "";
String userName = "";
String password = "";
/**
* 开始外部认证,认证结果会在认证回调onAuthSuccess,onAuthFailed,onAuthProgress中返回
*/
SFUemSDK.getInstance().startPasswordAuth(url,username,password);
注意:
- SDK集成外部认证的用户名是携带认证域的,所以格式上是:用户名@认证域,例如:zhangsan@ldap,具体认证域名称是在服务端配置,sdk携带域名需要与服务端配置保持一致(具体域名称找服务端管理员提供)
- SDK集成外部认证的密码,SDK会透传到aTrust服务端,aTrust服务端会透传到对应的外部认证服务器。故密码字段正常传入第三方密码或者口令。
特别注意: https认证的密码参数为第三方服务器需要的参数,通常以json格式传递(具体格式需要管理员根据实际https服务器要求在服务端配置),json数据中的key和value需要和服务器管理员在配置https认证服务器时配置的key, value一致,构建出json后,作为startPasswordAuth接口的password参数传入, 客户端只是透传数据, 不做任何解析动作, 最终如何和第三方服务器对接是由服务端认证配置决定的, 可以让深信服一线协助在服务端进行配置, 例如:
String url = "";
/**
*用户名@认证域,具体认证域根据服务端配置来
*/
String userName = "xxxx@https";
/**
* 传递单个信息可以直接放到密码字段直接传递,如果传递多个字段,建议使用json格式(也可以不是json格式,只是示例,可以随意自定义格式)sdk把整个 userName 和 password 当作字符串透传到服务端,服务端再去解析具体的值,或者直接传递第三方认证服务端对接
*/
String password = "{id:1,password:"123456"}";
/**
* 开始外部认证,认证结果会在认证回调onAuthSuccess,onAuthFailed,onAuthProgress中返回
*/
SFUemSDK.getInstance().startPasswordAuth(url,username,password);
服务器拿到password中的json数据会解析重组为第三方服务器所需的数据结构(服务端配置),然后代理访问第三方服务器,第三方服务器返回的信息会通过SDK的认证回调机制(onAuthSuccess)透传给用户侧,信息会保存在SFBaseMessage中的mServerInfo中;
4、认证成功
主认证成功后,如果管理员未配置二次认证,就会执行onAuthSuccess回调,至此整个认证流程就结束了,认证成功后,应用就可以正常的访问aTrust管理员配置的内网服务器资源, 执行业务代码
示例代码如下:
/**
* 认证成功
*
* @param message 认证成功message
*/
@Override
public void onAuthSuccess(SFBaseMessage message) {
SFLogN.info(TAG, "认证成功!");
//打印一下第三方服务器的返回的信息
SFLogN.info(TAG, "auth success:" + message.mServerInfo);
// 认证成功之后的业务
}
5、认证失败
如果有认证失败的情况,会执行onAuthFailed回调, 在该回调中提示用户,重新开始认证
示例代码如下:
/**
* 认证失败
*
* @param message 认证失败message
*/
@Override
public void onAuthFailed(SFBaseMessage message) {
SFLogN.info(TAG, "认证失败!" + message.mErrStr);
//打印一下第三方服务器的返回的信息
SFLogN.error2(TAG, "auth failed", "errMsg: " + message.mServerInfo);
// 重新开始认证或者其他逻辑
}
6、处理下一次认证
如果服务端配置了首次登陆强制修改密码,或者其他二次认证时,主认证成功后会回调此方法, 如果明确不需要适配二次认证, 建议在此回调给用户提示,让管理员调整配置
示例代码如下:
/**
* 主认证成功,但需要辅助认证(下一步认证)
*
* @param nextAuthType 下一步认证类型
* @param message 下一步认证信息
*/
@Override
public void onAuthProgress(SFAuthType nextAuthType, SFBaseMessage message) {
SFLogN.info(TAG, "需要下一次认证, 下一次认证类型: " + nextAuthType.name());
/**
* 服务端配置了首次登陆强制修改密码,或者其他二次认证时,认证时会回调此方法,
* 此时如果不打算适配二次认证,建议给用户提示,让管理员调整配置
*/
Toast.makeText(context, "暂不支持此种认证类型(" + nextAuthType.toString() + ")", Toast.LENGTH_LONG).show();
}
7、监听注销回调
sdk使用过程中有可能出现被注销的情况,如应用主动调用注销接口、服务端管理员主动让用户下线等,所以应用监听注销回调是必须的,避免出现sdk内部已经注销了,但是应用无感知,从而出现业务异常的问题; 注意:注销回调建议在应用全生命周期内进行监听,避免出现在某个页面监听,页面销毁后,注销事件丢失的问题,可以参考SDKDemo的处理方法:在sdk初始化后就用一个单例对象注册注销回调
示例代码如下:
/**
* 注销事件监听回调,推荐在Application里面监听, 避免出现认证开始了还未监听的问题
*/
SFUemSDK.getInstance().registerLogoutListener(new SFLogoutListener() {
@Override
public void onLogout(SFLogoutType type, SFBaseMessage message) {
SFLogN.info(TAG, "onLogout, message: " + message);
/**
* 收到注销事件,需要重新认证
*/
}
});
8、免密认证
sdk提供了免密认证的能力,即认证流程全部通过后,重启应用后,应用不需要再次使用用户名密码进行认证,可以直接调用免密认证接口进行认证上线
注意:
- 免密认证接口只需要在应用进程启动后调用一次,不用多次调用
- 免密认证不能完全取代主认证,因为用户主动注销或者管理员在控制台主动让用户下线等场景下,免密信息会失效,免密认证就会失败,所以应用需要在免密认证失败后,继续使用用户名密码进行认证,可以参考SDKDemo中的处理方式
示例代码如下:
/**
* 这里是自动免密认证接口,返回true表示认证成功,此时用户就可以进行资源访问了,
* 如果返回false,表示当前不满足自动免密条件,需要用户主动调用用户名密码认证接口
*/
if (SFUemSDK.getInstance().startAutoTicket()){
showToast("免密成功");
} else {
//继续用户名密码认证逻辑
}