Android SDK

EMM SecCom SDK能够帮助第三方应用获取穿透SAG并得到SSO认证所需的各种信息; 还可以实现内容的安全存储。第三方应用开发者,只需要下载 android SDK对应的开发包,导入当前项目中,便可以比较容易的实现与SAG,SSO以及安全存储的集成工作。

下面是针对安卓开发人员的开发指南,没有明确说明的地方,IDE都默认使用Android Studio,EMM SecCom SDK统一简称EMM SDK。

1. SDK下载地址

下载Android SDK

2. 导入

2.1 申请AppKey

要利用SDK的各项功能,前提是申请SDK的授权。 在EMM管理平台当中,点击:设置—管理平台—授权证书,在“EMM SDK授权”一项中,输入应用包名(作为应用程序ID),点击生成授权码。然后将生成的授权码拷贝,替换AndroidManifest.xml当中的“YOURAPPKEY”即可。

2.2  配置开发环境

如果使用Android Studio:

1)    将下载的jar包,拷贝到项目目录下面的“app/libs”文件夹,如果app目录下面不存在libs文件夹,则创建该文件夹

2)    打开android studio,在项目的“project”视图下,打开libs目录,右键点击导入的jar包,选择“Add As Library”,点击OK,完成导入

如果使用Eclipse:

1)    将下载的jar文件拷贝到工程的libs(或lib)目录下,

2)    选中libs(或lib)目录下的对应jar包,右键菜单中选择Build Path, 选择Add to Build Path将SDK添加到工程的引用目录中,完成导入

配置方式:

sdk的jar文件已经上传至Sonatype Nexus搭建的maven仓库。如果不希望通过下载方式导入sdk,也可以通过配置方式来实现。

a) 如果项目使用gradle,可以在build.gradle中加入如下配置:

repositories {
    mavenCentral()   
    maven {   
        url "http://192.168.22.206/nexus/content/repositories/thirdparty/"   
   }     
} 
dependencies {   
    compile 'com.nationsky.seccom.accredit:SecComSDK:1.0.1.100000025 '
}

b)如果项目使用maven,可以在pom.xml中添加如下配置:

<dependency>
  <groupId>com.nationsky.seccom.accredit</groupId>
  <artifactId>SecComSDK</artifactId>
  <version>1.0.1.100000030</version>
  <type>aar</type>
</dependency>

2.3 声明及权限配置

在AndroidManifest.xml当中,增加如下声明及权限:

<application >   
       <!-- 项目的其它配置... -->     
       <!--用于接收Host发送过来的rpToken广播-->
        <receiver android:name="com.idsmanager.ssosublibrary.receiver.RPTokenReceiver">  
                       <intent-filter>       
                                     <action android:name="com.idsmanager.ACTION_RECEIVE_TOKEN"/>  
                      </intent-filter>
       </receiver>     
       <!-- 【必须】 请将YOUR_APP_KEY修改为APP的appKey -->   
       <meta-data        
                       android:name="EMM_SDK_APP_KEY"       
                       android:value="YOUR_APP_KEY" />
</application> 
//App需要访问网络的权限 ,如果原来没有,请添加
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--申请Host帮助获取rpToken的权限-->
<uses-permission android:name="com.idsmanager.REQUEST_TOKEN_PERMISSION" />
<!--接收Host帮助获取rpToken的权限-->
<uses-permission android:name="com.idsmanager.RECEIVE_TOKEN_PERMISSION" />
<!--接收单点登出广播的权限--> 
<uses-permission android:name="com.idsmanager. SLO_PERMISSION " />    
 //其它需要的权限 ...

注:其中“YOUR_APP_KEY”需要从管理平台获取。在管理平台当中,点击:设置—管理平台—授权证书,在“EMM SDK授权”一项中,输入应用包名,点击生成授权码。然后将生成的授权码拷贝,替换AndroidManifest.xml当中的“YOUR_APP_KEY”即可。

2.4 证书导入

如果SDK的使用环境中包含SAG (proxy),那么要正常使用SDK的功能,需要与SAG和Emm服务器建立安全连接。这就需要导入SAG的自签名证书,并由SDK进行信任。开发人员只需要如下两个步骤:

1) 将证书名称修改为: nsky.bks

2) 将证书文件拷贝到src/main/assets目录下,参考下图:

证书导入

3. SDK调用

EMM SDK调用的入口类为NationskyEmmSDK。下面分别说明不同场景下对EMM SDK的调用。

3.1 SDK的初始化

  • int init(Context context)

初始化SDK,并返回错误码。

返回值 – 错误码:

    ErrorCode.NO_ERROR // SDK初始化成功
    ErrorCode.INIT_ERROR_CONTEXT_IS_NULL //Context为Null
    ErrorCode.INIT_ERROR_APP_KEY_NOT_SET // 未设置App Key
    ErrorCode.INIT_ERROR_APP_NOT_REGISTERED// 未注册App Key

示例代码:

   SecComSDK sdk = SecComSDK.getInstance()
    int errorCode = sdk.init();
    if(errorCode == ErrorCode.NO_ERROR){
        // init success
    }else{
        // init failed
    }

 3.2 激活EMM平台

  • PlatformActivationInfo activatePlatform(ActivationParameter parameter)

此API仅供EMM Client激活使用。 第三方APP不需要调用此API。

激活完成后,返回激活信息。

返回值 – 平台激活信息:

    public class PlatformActivationInfo {
        public String emmServerAddress; 
        public String idsServerAddress; 
        public String tokenAgentKey;
        public String tokenAgentSecret;
        public String emmAccessKey;
        public int errorCode;
    }

示例代码:

    PlatformActivationInfo info = sdk.activatePlatform(new ActivationParameter("tony","123456","192.168.22.191","443","mdm"));

 3.3 EMM验证

  • void activeByEMM(ActiveListener listener)

APP通过EMM验证合法性,并从EMM取得相关信息(这些信息SDK会自己保存)。

当APP需要依附EMM Client为主应用时,该APP第一次启动时,需要调用此函数实现EMM对此APP的验证。验证时,跳转至EMM解锁密码界面。用户输入EMM解锁密码成功后,跳转回该应用,继续后面的操作。

返回值 – 平台激活信息:

   public interface ActiveListener {
        void onReady(int errorCode);
    }

示例代码:

    sdk.getActivationParameter(new ActiveListener() {
        @Override
        public void onReady(int error) {
            if(error == ErrorCode.NO_ERROR)
                //do something
            else
                Log.d(TAG, "error is "+error);
        }
    });

 3.4 取得App Config信息

  • void getAppConfig(AppConfigListener listener)

通过EMM Client从平台取得App的配置信息。

返回值 – App Config信息:

    public interface AppConfigListener {
        void onFailure(int errorCode);
        void onSuccess(String jsonString);
    }

示例代码:

    sdk.getAppConfig(new AppConfigListener() {
        @Override
        public void onFailure(int errorCode) {
            //do somethig
        }
        @Override
        public void onSuccess(String jsonString) {
            //save app config info
        }
    });
  • void registerAppConfigUpdate(AppConfigListener listener)

注册App Config更新监听器。 当平台上App Config有变化时,通知SDK,并获取最新的App Config配置信息。

示例代码:

    sdk.registerAppConfigUpdate(new AppConfigListener() {
        @Override
        public void onFailure(int errorCode) {
            //save a fale to mark app config is changed. When use it, get it again.
        }
        @Override
        public void onSuccess(String jsonString) {
            //save app config info
        }
});

 3.5 取得Credit Info信息

如果第三方APP根据自己的业务,需要得到这些参数(AppPassToken, HostId, TenandId)时,可以调用此API。 如果业务中不需要这些参数,则不需要调用此API。 在生成NSCHttpClient时,SDK会内部调用,并从服务器得到穿过SAG(Proxy)需要的CreditInfo。

返回值 – Credit Info信息:

    public class AccreditInfo {
        public String appPassToken;
        public String tenantId;
        public String hostId; 
        public int errorCode;
    }
  • AccreditInfo getCreditInfo( )

取得穿过Proxy所需的信息。

返回值 – Credit Info信息:

示例代码:

  AccreditInfo info = sdk.getCreditInfo();
  • void getCreditInfo(AccreditInfoListener listener)

取得穿过Proxy所需的信息。

返回值 – Credit Info信息:

    public interface AccreditInfoListener {
        void onFailure(int errorCode);
        void onSuccess(AccreditInfo info);
    }

示例代码:

    sdk.getCreditInfo(new AccreditInfoListener() {
        @Override
        public void onFailure(int errorCode) {
            Log.d(TAG, "error is "+error);
        }
        @Override
        public void onSuccess(AccreditInfo info) {
            if(info.errorCode == ErrorCode.NO_ERROR){
                // save the AccreditInfo
            }
        }
    });

 3.6 取得可以穿过SAG的HttpClient

  • AbstractHttpClient getNSCHttpClient()

取得可以穿过SAG (Proxy)的HttpClient。此HttpClient里包含了穿过Proxy的信息及安全Tunnel,其用法与传统的HttpClient用法相同。

返回值 – AbstractHttpClient:

示例代码:

    AbstractHttpClient httpClient = getNSCHttpClient();

 3.7 单点登录

单点登陆需要以下的环境支持:

  • 与EMM Client配合完成,EMM Client做为Host应用完成激活和登录。
  • EMM的管理端需要为单点登陆的应用配置SSO的应用策略,并将带有此策略的应用推送至客户端。
  • void sso(String appUserName, SsoListener SsoListener, boolean proxySSO)

取得单点登录时需要的RP Token。 proxySSO标识布署场景中是否使用了Proxy。

调用此接口前需完成EMM Client的验证,即需完成activeByEMM的调用。

RPtoken 的使用:

  • Basic类型:需要在http header信息中添加

key: Authorization value: Basic 您的用户名:您的密码 Base64后的字符串

  • OAuth:类型: 需要在http header信息中添加

key: Authorization value: Basic rpToken(字符串),

  • OIDC类型:需要在http header信息中添加

key: Authorization value: Basic rpToken(字符串)     key: idToken value: idToken(字符串)

返回值 – RP Token信息:

    public interface SSOListener {
        void onFailure(int errorCode);
        void onSuccess(String token) ;
    }

示例代码:

 AbstractHttpClient httpClient = getSampleHttpClient();
    CredentialsProvider credsProvider = httpClient.getCredentialsProvider();
    credsProvider.setCredentials(
       AuthScope.ANY,
       new UsernamePasswordCredentials(“sample_accout@company.com”, ""));
       nscHttpClient.setCredentialsProvider(credsProvider);

    httpClient.setTargetAuthenticationHandler(new NegotiateTargetAuthenticationHandler());
    AuthSchemeRegistry authSchemeRegistry = new AuthSchemeRegistry();
    authSchemeRegistry.register("Basic", new BasicSchemeFactory());
    authSchemeRegistry.register("Negotiate", new NSCNegotiateSchemeFactory());
    httpClient.setAuthSchemes(authSchemeRegistry);

 3.8 结束SDK的使用

  • void finish()

为避免内存泄露,请在使用结束后调用此API。

示例代码:

  sdk.finish();

 3.9 Secure Storage的调用

Secure SDK调用的入口类为SecComSDK。

3.9.1 初始化

  • static void InitSecureStorage ()

示例代码:

SecComSDK sdk = SecComSDK.getInstance();
sdk.InitSecureStorage();

 3.9.2 设置密钥

  • static void setSecureStorageKey (String key)

该密匙讲用于对数据库和文件的安全存储

示例代码:

String myKey = “123456789”;
SecComSDK sdk = SecComSDK.getInstance();
sdk.setSecureStorageKey(myKey);

 3.9.3 安全数据库存储

应用安全数据库的途径是通过替换android原生包(android.database和android.database.sqlite)来实现的。

需要将应用程序中所有数据库原生类替换为SecureSDK实现的数据库类(仅需要对包名进行更改,无需对具体方法进行更改)。数据库具体使用方法可以参考Andoid API文档。

注意:除LOCALIZED 和 UNICODE collators之外,SecureSDK支持所有原生包中提供的API。

具体替换方法举例如下:

原始代码:

    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteException;

替换代码:

    import com.nationsky.seccom.database.sqlite.SQLiteDatabase;
    import com.nationsky.seccom.database.sqlite.SQLiteException;

 3.9.4 安全文件存储

安全文件存储采用流加密方式,可对网络数据流进行无缝加密,也可以读取本地文件流后进行加密。

应用安全文件的途径是通过替换android原生包(java.io.FileInputStream和java.io.FileOutputStream)来实现的。(仅需要对包名进行更改,无需对具体方法进行更改)

3.9.5 加密

需将java.io.FileOutputStream替换为com.nationsky.seccom.io.FileOutputStream

具体替换方法举例如下:

原始代码:

    import java.io.FileOutputStream;

替换代码:

    import com.nationsky.seccom.io.FileOutputStream;

 3.9.6 解密

需将java.io.FileInputStream替换为com.nationsky.seccom.io.FileInputStream

具体替换方法举例如下:

原始代码:

    import java.io.FileInputStream;

替换代码:

    import com.nationsky.seccom.io.FileInputStream;

 4. 错误码

错误码定义, 小于0的错误码表示, 错误发生在客户端;大于0的错误码,表示错误发生在服务器端,错误码由服务端定义。

返回的对象结构中,可能包含如下的错误代码:

代码命名 取值 描述
NO_ERROR 0  调用完成, 没有错误发生
OPER_FAIL -1  操作失败
INIT_ERROR_CONTEXT_IS_NULL -2 初始化失败, Context为空
INIT_ERROR_APP_KEY_NOT_SET -3 初始化失败,App Key没有设置
INIT_ERROR_APP_NOT_REGISTERED -4 初始化失败,App没有注册
INIT_ERROR_NOT_FINISHED -5 初始化未完成
SERVER_CONNECT_ERROR -6 服务连接失败
EMM_UNEXPECTED_CRASH -7 EMM 发生异常
EMM_NOT_INSTALLED -8 EMM未安装
EMM_NOT_ACTIVATED -9 EMM 未激活
EMM_NOT_LOGGEDIN -10 EMM 未登录
INVALID_PARAMETER -11 参数错误
SSO_BASIC_TOKEN_IS_NULL -12  Basic token 错误
SSO_HOST_LOGIN_RETRY_EXCEED -13 Host 登录失败
SSO_NOT_ACTIVE_BY_EMM -14 SSO前需先进行EMM验证
ERROR_HOST_NOT_LOGIN 101 EMM (Host)未登录
ERROR_HOST_LOGIN_TIMEOUT 102 EMM(Host)登录超时
ERROR_REQUEST_TOKEN_ILLEGAL 103 请求的Token非法
ERROR_GET_TOKEN_SERVER_ERROR 104 IDS服务器错误
ERROR_FACET_ID_ERROR 106 FacetId错误
ERROR_GET_RP_TOKEN_FAILED 111 请求RPToken失败
ERROR_REQUEST_USER_EMPTY 112 用户名为空
ERROR_NO_HOST_FOUND 113 Host应用未发现
RP_LOGIN_FAIL 201 RP login 失败
RP_SERVER_EMPTY 202 RP 服务器地址为空,需要添加SSO策略,
HEADERINFO_NOT_ENOUGH 301 http Header 信息错误
ERROR_NO_RELATIONSHIP_EMM_RP 302 EMM用户未与RP用户正确关联
ERROR_IDS_SERVER 303 IDS服务器出错
ERROR_GRANT_ID 304 Grantid出错
ERROR_REQ_PARAMETER 305 请求参数检查失败
ERROR_TOKEN_EXPIRED 306 Token已过期
ERROR_TOKEN_GEN_FAILED 307 id_token生成失败
ERROR_EMM_SERVER_EXCEPTION 311 EMM服务器异常
ERROR_OAUTH 333 Oauth获取token调用发生错误或返回数据错误
ERROR_NO_RP_INFO 315 没有找到对应的RP信息
ERROR_FUN_NO_FINISHED 317 功能尚未实现
ERROR_KERBEROS_EXCEPTION 344 Kerberos Server异常
ERROR_UNAUTH 401 未授权或者token失效
APP_CONFIG_NULL 1006 配置信息为空或处在非激活状态
APP_CONFIG_DISABLE 1008 应用配置未启用
APP_SSO_DISABLE 1010 sso未启用