设备指纹Android端接入文档

2024.03.12 15:54:59

    接入说明

    接入流程

    接入设备指纹SDK,开发者需要完成以下步骤

    1. 将SDK拷贝到指定工程目录;
    2. 修改项目配置;
    3. 初始化SDK;
    4. 调用SDK获取token接口函数;
    5. 验证SDK接入是否正确;
    

    法规需求

    根据我国《网络安全法》等相关法律法规及国家标准的要求,个人信息的收集和使用,应当遵循合法、正当、必要的原则,公开收集、使用规则,明示收集、使用信息的目的、方式和范围,并经被收集者同意。故我们强烈建议您在拟接入易盾安全SDK前,检查和完善拟接入软件的《隐私政策》中有关采集个人信息部分的说明,确保已涵盖拟接入SDK项下需要采集的个人信息(详见附表),并明确您有权将上述个人信息提供给第三方用于安全服务。

    规范里要求涉及到用户隐私、设备敏感信息的数据采集均需要在隐私政策中明确声明,并需要弹窗由用户确认,在未确认弹窗前,不允许进行采集,当用户不同意时,同样不允许进行采集。

    详情请参照网易易盾隐私政策,请放到应用“隐私协议”中。

    1. 隐私政策补充(根据实际情况进行调整)

    为提高您使用我们产品时的安全性,保障您的账号安全,我们将获取并记录您的设备相关信息,包括设备型号,操作系统类型,网络状态,设备唯一识别码(包含IMEI,无线Mac地址,Android ID,广告ID,OAID,设备序列号),设备环境信息来判断您的账户/设备是否存在风险。

    附表:

    采集信息类型 是否采集 是否需要授权 备注
    设备型号
    设备IP地址
    设备MAC地址
    设备唯一标识码(IMEI) SDK 1.7.2.3后不采集
    设备序列号SN SDK 1.8.0后不采集
    Android ID
    设备唯一标识码(MEID)
    蓝牙MAC地址
    传感器数据
    定位信息
    基站信息
    APK安装列表
    无线网络SSID
    无线网络BSSID

    2. 三方SDK采集说明

    为保证符合国家隐私合规政策,需要在隐私政策中的三方SDK列表中补充易盾设备安全SDK相关说明

    SDK名称 公司 SDK用途 收集个人信息字段
    易盾设备安全SDK 杭州网易智企科技有限公司 用于风险控制、反欺诈、设备环境风险,以保障账户和交易安全 唯一设备识别码(AndroidID、OAID、GAID、Mac地址);设备运行状态(SIM卡状态、USB状态、充电状态、电池容量及电量、启动时间);设备基本信息(设备品牌及型号、设备厂商、设备所运行系统版本、名称、系统内核信息、CPU型号、设备内存及存储大小、屏幕亮度及分辨率、设备架构、基带信息、辅助功能列表、模拟器类型);日志信息(网络连接类型及状态、IP地址、运营商信息、网络代理、WIFI信息)。
    申请权限 个人信息对外传输/共享 SDK隐私政策链接 联系方式
    网络权限 是否传输/共享:是
    传输/共享对象:杭州网易智企科技有限公司
    **涉及传输信息:**唯一设备识别码(AndroidID、OAID、GAID、Mac地址);设备运行状态(SIM卡状态、USB状态、充电状态、电池容量及电量、启动时间);设备基本信息(设备品牌及型号、设备厂商、设备所运行系统版本、名称、系统内核信息、CPU型号、设备内存及存储大小、屏幕亮度及分辨率、设备架构、基带信息、辅助功能列表、模拟器类型);日志信息(网络连接类型及状态、IP地址、运营商信息、网络代理、WIFI信息)。
    传输方式:https
    https://dun.163.com/clause/privacy Privacy@service.netease.com

    注:SDK版本1.7.2.3之后不再获取IMEI,接入此后版本时,可以将表格中IMEI删除

    接入步骤

    导入sdk

    以Android Studio为例,将获取到的sdk的aar文件放到工程中的libs文件夹下,然后在app的build.gradle文件中增加如下代码

    repositories {
        flatDir {
            dirs 'libs'
        }
    }
    

    在build.gradle配置文件的 dependencies依赖中增加对aar包的引用(x.x.x表示版本号,请联系技术支持确认最新的版本号):

    dependencies {
        implementation (name:'NEDevice-SdkRelease_vx.x.x', ext:'aar')
    }
    

    在Android Studio中开启Java8的支持

    android {
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }
    }
    

    配置过滤ABI

    SDK提供了armeabi、armeabi-v7a、x86、arm64-v8a、x86_64五种ABI的支持,默认会支持这五种ABI。

    注意:

    • 如果产品本身不支持这么多ABI,就需要对最终导出的ABI进行过滤,否则会导致崩溃
    • 如果app只需要支持特定的ABI,比如armeabi、armeabi-v7a、x86三种,可以在build.gradle添加如下配置:
    defaultConfig {
        applicationId "com.XX.XXX"
        minSdkVersion XX
        targetSdkVersion XX
        versionCode XX
        versionName "X.X.X"
        ndk {
            abiFilters "armeabi", "armeabi-v7a", "x86"
        }
    }
    

    添加权限信息

    SDK不会主动申请任何权限,但是为了提升设备指纹的效果,建议在 AndroidManifest.xml 文件中添加下列权限配置(以 aar 接入则不需要配置):

     <!--网络通信-->
    <uses-permission android:name="android.permission.INTERNET" /> //必须
     <!--获取WIFI状态-->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> //必须
     <!--获取网络状态-->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> //必须
    
     <!--OAID广告ID相关-->
    <uses-permission android:name="com.asus.msa.SupplementaryDID.ACCESS" /> 
    <uses-permission android:name="com.asus.permission.READ_SDID_PROVIDER" />
    <!--asus oaid-->
    <uses-permission android:name="freemme.permission.msa" />
    <!--freeme-->
    

    若当前应用目标SDK版本设置在29及以上时,可以通过添加以下配置增强OAID能力(可选),不设置可能无法获取到OAID。

    <queries>
        <package android:name="com.heytap.openid" />
        <package android:name="com.mdid.msa" />
        <package android:name="com.android.creator" />
        <package android:name="com.coolpad.deviceidsupport" />
        <package android:name="com.asus.msa.SupplementaryDID" />
        <package android:name="com.samsung.android.deviceidservice" />
    </queries>
    

    若当前应用目标SDK版本设置在31及以上时,需要添加以下权限以获取谷歌广告ID(可选),建议添加:

    <uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
    
    私有化接入注意事项

    当targetSdkVersion大于等于28时,Android 9及以上系统默认不允许使用http请求,如果使用请求为http(如http://xxx.xxx.xx/xx),需要在AndroidManifest.xml中增加相关配置:

        <?xml version="1.0" encoding="utf-8"?>
        <manifest ... >	
    		<application
        		android:usesCleartextTraffic="true"
        		...
    		</application>
        </manifest>
    

    或者仅针对指定域名允许HTTP请求,需要在AndroidManifest.xml中声明android:networkSecurityConfig属性

        <?xml version="1.0" encoding="utf-8"?>
        <manifest ... >
            <application android:networkSecurityConfig="@xml/network_security_config"
                            ... >
                ...
            </application>
        </manifest>
    

    network_security_config.xml配置如下

    <network-security-config>
    	<domain-config cleartextTrafficPermitted="true">
            <domain includeSubdomains="true">xxx.xxx</domain>  //配置设备指纹私有服务域名
        </domain-config>
    </network-security-config>
    

    添加ProGuard配置

    若使用ProGuard进行混淆,需要将SDK使用的类排除掉。若使用Android studio开发,则在proguard-rules.pro文件里添加如下信息:

     -keep class com.netease.mobsec.xs.**{*;}
    

    SDK接入调用说明

    多业务接入请参考 SDK多业务接入说明

    SDK初始化

    接口用途:

    用于初始化设备指纹SDK。

    接入须知:

    使用其他接口之前,必须先调用初始化接口。建议在用户同意隐私协议后调用。

    函数原型:
    public boolean init (Context context,String appId);
    public boolean init (Context context,String appId,String channel);
    public boolean init (Context context,String appId,String channel,NTESCSConfig config);
    
    //新增接口,以下接口在SDK 1.7.2.5及以上版本支持
    public int initV2(Context context, String appId);
    public int initV2(Context context, String appId, String channel);
    public int initV2(Context context, String appId, String channel, NTESCSConfig config);
    

    返回值说明

    init接口初始化成功时,返回true,initV2接口成功时返回200

    参数说明:
    参数 说明
    context 当前环境的上下文
    appId 易盾分配appId(32位),对应管理后台分配的BusinessID
    channel 渠道信息(可选),建议配置,或可以传入空字符串
    NTESCSConfig 配置接口(可选),一般不需要配置,私有化接入时配置

    appId请联系易盾获取。

    NTESCSConfig说明:
    方法 支持版本 默认配置 说明
    setUrl 全部 易盾接口 配置上报数据接口服务端,仅针对私有化部署时配置
    setTimeout 1.6.4 + 5000ms 配置上报数据接口超时时间,单位毫秒
    setCacheTime 1.6.7+ 不缓存 配置token缓存时间,单位为分钟,token服务端过期时间为1小时,建议缓存最大不超过30分钟
    setDevInfo 1.8.2+ 配置是否采集额外的设备数据,默认开启,可主动设置false关闭
    setOverseas 1.8.2+ 配置是否使用海外接口进行数据上报,一般不用设置,海外app可主动设置为true
    setCollectWifiInfo 1.8.5+ 配置是否采集wifi相关信息,默认不采集,开启后需要在隐私政策上说明
    setNetClient 1.9.2+ 配置是否网络数据通过自实现接口发送,默认走SDK内部网络,自实现见附录

    注意:配置超时后会同时作用在连接和读取数据上,实际超时时间会乘以2,例配置5000ms时,实际超时时间为10秒

    示例代码:
    ....
    import com.netease.mobsec.xs.NTESCSDevice;       // 调入sdk的接口类
    ....
    
    public class MainActivity extends AppCompatActivity {
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    		....
            Context mContext = getApplicationContext();
            //为保证符合隐私政策规范,建议 init 控制在用户同意隐私政策后
            
            //saas接入参考
            NTESCSDevice.get().init(mContext, "your appid");  //调用sdk初始化接口init函数,channel字段可选,如需统计不同渠道,建议配置
    		....
                
            //以下配置仅针对私有化场景,使用saas版本时不需要配置
            NTESCSConfig config = new NTESCSConfig();
            config.setUrl("https://xxx.xxx.com/vx/xx/xx");
            NTESCSDevice.get().init(this, "your appid", "your app channel", config);
        }
    
    }
    

    initV2状态码说明:

    code 说明
    200 SDK初始化成功
    1007 SDK初始化参数校验异常,如Context为空或者appId格式异常
    1008 SDK当前初始化在非主进程内,必须要在主进程内执行初始化
    1009 SDK私有化URL地址校验失败,必须以http://或者https://开头(仅针对私有化时使用)
    1010 SDK初始化加载SO文件异常,请确保已正常集成SDK或者ABI过滤正确
    1011 SDK初始化函数加载异常,请确保配置正确

    获取动态Token

    接口用途:

    获取设备指纹采集凭证,用作后续查询设备指纹及风险。

    接入须知:

    必须在 init 之后才可调用该接口,getToken支持同步和异步调用,异步接口回调数据在主线程,建议每次重新启动app时获取token,该接口调用后会立即触发数据采集,考虑合规风险,请勿频繁调用。

    函数原型:
    public void getToken(NECallback callback);    //异步接口
    public Result getToken();                     //同步接口,不可在主线程运行
    

    注意: getToken(NECallback callback)内部为单线程设计,同时执行多次会出现阻塞,同步接口不要多线程同时执行

    参数说明:
    参数 说明 赋值
    NECallback onResult回调接口,Result对象

    Result字段说明:

    KEY名称 KEY类型 KEY值 说明
    状态码 int getCode() 回调状态码
    token信息 字符串 getToken() 回调token
    示例代码:
    public void rise() {
          //获取设备指纹查询token,异步
          //注意,如果使用runBlocking协程方式调用,可能会无法回调,建议使用常规模式获取
    	  NTESCSDevice.get().getToken(new NECallback(){
    		  @Override
    		  public void onResult(Result result) {
                  //callback会返回在主线程中
    			  if(result.getCode()==200){ //code码说明见下方表格
                      //result.getToken()
                   }else if(result.getCode()==201){
                      //result.getToken() //离线模式下,token长度可能为2000-3000字节,格式为base64 urlsafe编码
    			   }
    		  }
    	  });
        
            //或者使用同步模式,二选一
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Result result = NTESCSDevice.get().getToken();
                    if (result.getCode() == 200 || result.getCode() == 201) {
                        result.getToken();
                    }
                }
            }).start();
        
    }
    
    Token使用:

    当客户端SDK获取到token后,将token提交到业务后端调用易盾接口获取设备指纹和环境风险结果,考虑到安全性问题,请勿在客户端调用易盾指纹查询接口

    离线Token解释:

    当网络出现异常或者SDK请求服务端超时时,会返回状态码201,且token会扩充到2000-3000字节长度,此时的token可以当作正常token使用,避免因网络问题获取不到token而对业务产生影响,如果业务对token或者请求包长度有控制,可以忽略该状态码下的token,只使用状态码为200下的正常token

    状态码说明:
    code 说明
    200 请求成功,返回正常token
    201 网络异常或者发送数据失败时会返回离线base64数据,可认为成功,长度为2000-3000字节,数据与正常token最终效果一致,传输时需注意编码问题,如业务上限制数据包大小,可忽略该状态码
    1000 本地采集数据异常
    1002 服务端返回数据解析异常
    1003 SDK未初始化或初始化失败
    1005 服务端返回数据校验异常
    1006 同步getToken模式运行在主线程错误码
    4xx 服务端接口相关异常状态码,具体参考后端接入文档
    5xx 服务端接口相关异常状态码,具体参考后端接入文档

    SDK多业务接入说明

    **说明:**多业务是指不同业务间使用不同的appId或BusinessID分别调用SDK获取token,保障各业务间的独立性

    **注意:**多业务下暂不支持私有化系统,并且业务之间应当全部使用NEDevice接口

    SDK多业务初始化

    接口用途:

    用于初始化设备指纹SDK。

    接入须知:

    使用其他接口之前,必须先调用初始化接口,只需要初始化一次即可。建议在用户同意隐私协议后调用。

    函数原型:
    public int init(Context context);
    

    返回值说明

    init接口初始化成功时返回200

    参数说明:
    参数 说明
    context 当前环境的上下文
    示例代码:
    ....
    import com.netease.mobsec.xs.NEDevice;       // 调入sdk的接口类
    ....
    
    public class MainActivity extends AppCompatActivity {
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    		....
            Context mContext = getApplicationContext();
            //为保证符合隐私政策规范,建议 init 控制在用户同意隐私政策后
            
            //saas接入参考
            NEDevice.get().init(mContext);  //调用sdk初始化接口init函数
        }
    
    }
    

    init状态码说明:

    code 说明
    200 SDK初始化成功
    1007 SDK初始化参数校验异常,如Context为空
    1008 SDK当前初始化在非主进程内,必须要在主进程内执行初始化
    1010 SDK初始化加载SO文件异常,请确保已正常集成SDK或者ABI过滤正确
    1011 SDK初始化函数加载异常,请确保配置正确

    多业务获取动态Token

    接口用途:

    获取设备指纹采集凭证,用作后续查询设备指纹及风险。

    接入须知:

    必须在 init 之后才可调用该接口,getToken目前仅支持异步调用,异步接口回调成功数据在主线程,建议每次重新启动app时获取token,该接口调用后会立即触发数据采集,考虑合规风险,请勿频繁调用。

    请注意appId校验失败及未初始化调用getToken返回的callback返回在调用线程

    函数原型:
    public void getToken(String appId,NECallback callback);                                    //异步接口
    public void getToken(String appId,String channel,NECallback callback);                     //异步接口
    

    注意: getToken内部为单线程设计,同时执行多次会出现阻塞。

    参数说明:
    参数 说明 赋值
    appId 产品ID或业务ID 必填,由易盾提供
    channel 渠道信息 可选
    NECallback onResult回调接口,Result对象 必填

    Result字段说明:

    KEY名称 KEY类型 KEY值 说明
    状态码 int getCode() 回调状态码
    token信息 字符串 getToken() 回调token
    示例代码:
    public void rise() {
          //获取设备指纹查询token,异步
          //注意,如果使用runBlocking协程方式调用,可能会无法回调
    	  NEDevice.get().getToken("your appid",new NECallback(){
    		  @Override
    		  public void onResult(Result result) {
                  //callback会返回在主线程中
    			  if(result.getCode()==200){ //code码说明见下方表格
                      //result.getToken()
                   }else if(result.getCode()==201){
                      //result.getToken() //离线模式下,token长度可能为2000-3000字节,格式为base64 urlsafe编码
    			   }
    		  }
    	  });  
        
        ...
            
        //设置渠道信息参考
        NEDevice.get().getToken("your appid","wandoujia",new NECallback(){
        ...
        });    
    }
    
    状态码说明:
    code 说明
    200 请求成功,返回正常token
    201 网络异常或者发送数据失败时会返回离线base64数据,可认为成功,长度为2000-3000字节,数据与正常token最终效果一致,传输时需注意编码问题,如业务上限制数据包大小,可忽略该状态码
    1000 本地采集数据异常
    1002 服务端返回数据解析异常
    1003 SDK未初始化或初始化失败
    1005 服务端返回数据校验异常
    1007 getToken校验appId错误,请确认传入正确的appId
    1008 表示getToken时线程异常,主要是线程堆积导致
    4xx 服务端接口相关异常状态码,具体参考后端接入文档
    5xx 服务端接口相关异常状态码,具体参考后端接入文档

    附录

    自实现网络接口:

    传输协议:HTTPS

    传输方式:POST

    传输数据类型:二进制流 application/octet-stream;charset=utf-8

            NTESCSConfig config = new NTESCSConfig();
            config.setNetClient(new NTESCSNetClient() {
                @Override
                public String sendPost(String url, int timeout, byte[] data) {
                    //请内部处理异常,不要对外抛出异常,当出现异常时,可以返回空字符串或者null
                    HttpURLConnection conn = null;
                    try {
                        URL u = new URL(url);
                        conn = (HttpURLConnection) u.openConnection();
                        if (conn instanceof HttpsURLConnection) {
                            SSLContext sc = SSLContext.getInstance("TLS");
                            //如有证书校验逻辑,请自实现
                            sc.init(null, null, new SecureRandom());
                            ((HttpsURLConnection) conn).setSSLSocketFactory(sc.getSocketFactory());
                        }
                        //注意上报协议形式必须是POST
                        conn.setRequestMethod("POST");
                        //上报数据形式为二进制流
                        conn.setRequestProperty("Content-Type", "application/octet-stream;charset=utf-8");
                        conn.setDoOutput(true);
                        conn.setDoInput(true);
                        //Android中的timeout会分别对应setConnectTimeout和setReadTimeout两个函数,实际超时时间会乘以2
                        conn.setConnectTimeout(timeout);
                        conn.setReadTimeout(timeout);
                        conn.setUseCaches(false);
                        conn.setFixedLengthStreamingMode(data.length);
                        DataOutputStream out = new DataOutputStream(conn.getOutputStream());
                        out.write(data);
                        out.flush();
                        out.close();
                        int code = conn.getResponseCode();
                        if (code != HttpURLConnection.HTTP_OK) {
                            return null;
                        }
                        return IOUtils.inputStream2String(conn.getInputStream(), "UTF-8");
                    } catch (Exception ignored) {
    
                    } finally {
                        if (conn != null) {
                            conn.disconnect();
                        }
                    }
                    return null;
                }
            });
            //实现完成后,请务必将config传入初始化接口中,否则将无法生效
            NTESCSDevice.get().initV2(this, "product number", "your channel", config);
    
    Online Chat Tel:95163223 Free trial