乐趣区

关于安全:设备指纹系列前端篇

根底篇请看:设施指纹系列 – 根底篇

咱们接着前文持续写对于设施指纹前端接入方面的内容。话不多说,间接步入正题。

咱们会在下文展现 5 种前端接入的形式,包含web 接入、安卓接入、ios 接入、微信小程序接入以及支付宝小程序接入

Web 接入

第一步:引入

在页面 HTML 中引入 const-id.js,代码形如:

<script src="https://cdn.dingxiang-inc.com/ctu-group/constid-js/index.js"></script>

因 js 文件会定期更新,为防止 js 生效影响您的应用,请不要将 js 下载到本地服务器上引入

第二步:生成并应用

页面加载后,初始化设施指纹,须要在 JavaScript 中调用 _dx.ConstID(options, callback) 办法获取设施指纹 token,代码形如:

var options = {
  appId: '【这里填写 AppID】', // 惟一标识,必填
  server: 'https://constid.dingxiang-inc.com/udid/c1', // constId 服务接口,可选
  userId: '【这里填写 userID】' // 用户标识,可选
};

_dx.ConstID(options, function (err, token) {if (err) {// console.log('error:' + err);
    return;
  }
  // console.log('const-id token is' + token);
});

同时也反对 Promise 的用法

_dx.ConstID(options).then(function(token) {console.log(token)
}).catch(function(err) {console.log(err)
})

options 字段阐明

字段 类型 是否必填 阐明
appId String 以后利用的标识
server String constId 服务接口,可选,如不填,则默认会用云服务接口
scene String 场景标识,例如 loginsurvey 等
userId String 业务方的用户惟一标识,例如用户名、用户 ID、手机号、Email 等
timeout number 超时失败工夫,单位为毫秒
cache boolean 默认为 true,示意会缓存采集后果;改为 false 则每次会从新采集

PC 浏览器兼容

浏览器 最低版本
IE 8
Edge 20
Chrome 60
Safari 11
Firefox 60
360 10
Sougou 8
QQ 4

挪动端浏览器兼容

浏览器 最低版本
Chrome 60
UC 12
QQ 8
Safari 11
原生 安卓 4.0 及以上

安卓接入

一、环境要求

条目 阐明
开发指标 Android 4.0+
开发环境 Android Studio 3.0.1 或者 Eclipse + ADT
CPU 架构 ARM 或者 x86
SDK 三方依赖

二、集成 SDK

2.1 下载 SDK

点击下载 SDK

点击下载 demo(仅做代码配置演示应用)

2.2 Android Studio 集成

SDK 包集成内容:

  • dx-risk-vx.x.x.aar
2.2.1 把 aar 文件放到相应模块的 libs 目录下

Demo 工程构造如下

.
├── app
│   ├── build.gradle
│   ├── libs
│   │   └── dx-risk-vx.x.xxr.xxxxxxxx.aar
│   ├── proguard-rules.pro
│   └── src
│       └── main
├── build.gradle
├── gradle
├── gradle.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
2.2.2 在该 Module 的 build.gradle 中如下配置:
android {

  packagingOptions {doNotStrip "**/lib*Risk*.so"}
}

dependencies {implementation fileTree(dir: 'libs', include: ['*.aar'])
}

2.3(可选)增加 SDK 所需权限

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>

2.4 Proguard 混同配置

-dontskipnonpubliclibraryclassmembers
-keepattributes *Annotation*,EnclosingMethod

-dontwarn com.dx.mobile.**
-dontwarn *.com.dx.mobile.**
-dontwarn *.com.mobile.strenc.**
-keep class com.dx.mobile.risk.**{*;}
-keep class com.security.inner.**{*;}
-keep class *.com.dx.mobile.**{*;}
-keep class *.com.mobile.strenc.**{*;}

2.5 API 6.0 或以上动静权限申请阐明

须要动静申请权限如下:

android.permission.WRITE_EXTERNAL_STORAGE
android.permission.READ_EXTERNAL_STORAGE
android.permission.READ_PHONE_STATE
android.permission.ACCESS_COARSE_LOCATION
android.permission.ACCESS_FINE_LOCATION

动静申请代码实例(Activity 下):

protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_demo);

   // API 23 或以上的动静申请权限
   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {String[] permissionArray = {
               "android.permission.ACCESS_COARSE_LOCATION",
               "android.permission.ACCESS_FINE_LOCATION",
                "android.permission.ACCESS_BACKGROUND_LOCATION",
               "android.permission.WRITE_EXTERNAL_STORAGE",
               "android.permission.READ_EXTERNAL_STORAGE",
               "android.permission.READ_PHONE_STATE",
       };
       this.requestPermissions(permissionArray, 1);
   }

}


@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);
   // start getToken
   new Thread(new Runnable() {
       @Override
       public void run() {HashMap<String, String> params = new HashMap<String, String>();
           String token = DXRisk.getToken("appid", params);
       }
   }).start();}

三. 接口应用阐明

3.1 办法和参数阐明
性能形容

采集端的设施指纹信息,上传至风控后盾,再由风控后盾返回 token。该 API 为耗时操作,因而必须在非主线程上调用,否则会抛异样。

办法阐明

DXRisk.java 该类是 DxRisk SDK 的风控组件接口,负责采集本地信息并返回用户前端 token。

隐衷采集白名单

自 v6.1.18r 开始,SDKsetup 前,能够调用 setAllowPrivacyList 进行隐衷采集白名单的设置,默认敞开所有波及隐衷标准红线的采集项

public static void setAllowPrivacyList(long privacyFlag)

应用示例

setAllowPrivacyList(PrivacyFlag.ANDROID_ID); // 只采集 ANDROID_ID

<!—->

// 自定义列表模式
setAllowPrivacyList(PrivacyFlag.X | PrivacyFlag.Y | ...); // 示意既采集 X 又采集 Y,X、Y 示意具体某项采集的 FLAG 值,如下表

以下为提供的白名单采集项

FLAG 形容
DEFAULT 默认值,敞开所有隐衷采集项
ALL 关上所有隐衷采集项
IMEI 退出该 FLAG 则采集手机 IMEI 值,否则不采集
IMSI 退出该 FLAG 则采集手机 IMSI 值,否则不采集
MEID 退出该 FLAG 则采集手机 MEID 值,否则不采集
SERIAL\_NUMBER 退出该 FLAG 则采集手机 SERIAL\_NUMBER 值,否则不采集
MAC\_ADDRESS 退出该 FLAG 则采集手机 MAC\_ADDRESS 值,否则不采集
ICCID 退出该 FLAG 则采集手机 ICCID 值,否则不采集
ANDROID\_ID 退出该 FLAG 则采集手机 ANDROID\_ID 值,否则不采集
DEVICE\_ID 退出该 FLAG 则采集手机 DEVICE\_ID 值,否则不采集
GET\_INSTALLED\_PACKAGES 退出该 FLAG 则采集手机的利用装置列表,否则不采集
初始化 setup

SDK应用前必须调用先 setupsetup 次要用于数据 / 环境初始化,个别在 ApplicationonCreate下调用:

/**
* 初始化参数,环境
* @param context
* @return
*/
public static boolean setup(Context context)

PS:下列两种形式获取 token 在网络通顺的状况下没有任何的不同。

惯例 Token
/**
 * @return token 通常返回长度为 40 的字符串。在网络卡顿或不通的状况下,返回 4 -5k 的字符串。* @throws DXRiskErrorException 如在主线程调用本 API,或者 appId 为空等等,则会抛出该异样
 */
public static String getToken(String appId, HashMap<String, String> paramsMap) throws DXRiskErrorException
精简 Token

获取轻量级 Token 可获取的设施信息信息远少于 getToken(),可能会造成在判断设施是否有危险时呈现较大误差,请审慎应用。

/**
 `* @return token 通常返回长度为 40 的字符串。在网络卡顿或不通的状况下,返回 1k 的字符串。`* @throws DXRiskErrorException 如在主线程调用本 API,或者 appId 为空等等,则会抛出该异样
 */
public static String getLightToken(String appId, HashMap<String, String> paramsMap) throws DXRiskErrorException

3.2 应用示例

3.2.1 初始化 setup

倡议 Application.onCreate 下调用

@Override
public void onCreate() {super.onCreate();    
  // 环境初始化
  DXRisk.setup(this);
}
3.2.2 获取 token

整个过程因为是耗时操作,必须要在非主线程上执行,否则会 crash

new Thread(){

    @Override
    public void run() {
      /* 私有化配置 */
      HashMap<String, String> params = new HashMap<String, String>();
      // 这里请填写对应的服务端 url,留神 SAAS 和私有化的区别
      params.put(DXRisk.KEY_URL, "https://constid.dingxiang-inc.com");
      // 开启线上数据备份 
      // params.put(DXRisk.KEY_BACKUP, DXRisk.VALUE_ENABLE_BACKUP);
      // 设置申请 token 超时时长 ms,不设置默认为 500ms
      params.put(DXRisk.KEY_DELAY_MS_TIME, "2000");
      // 此配置敞开 SDK 缓存,示意每次调用接口都是强制采集信息
      // params.put("PRIVATE_CLEAR_TOKEN", "clear");
      // 开明服务后可在利用治理菜单中获取;私有化版本请填写私有化 appId
      String appId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
       // 获取设施指纹 token
      final String token = DXRisk.getToken(appId, params);

      // TODO 把 token 通过 Post 申请,传到用户后端
  }
}.start();

3.3 异样阐明

在获取 token 过程中,如果因为网络超时或者加解密失败,该接口有可能会返回为 null,同时会输入 tag 为 DXRISK 的错误信息,具体形容如下:

DXRISK_REQUEST_NETWORK_ERR            -1001         // 网络链接失败
DXRISK_REQUEST_DECRYPT_ERR            -1002         // 数据解密谬误
DXRISK_REQUEST_UNCOMPRESS_ERR         -1003         // 解压谬误
DXRISK_REQUEST_RESPONSE_EMPTY_ERR     -1004         // 返回为空
DXRISK_REQUEST_DATA_PARSE_ERR         -1005         // 数据解析失败
DXRISK_REQUEST_DIRTY_DATA_ERR         -1006         // 脏数据
DXRISK_CONST_ID_EMPTY                 -1007         //constid 为空

ios 接入

一、环境需要

条目 阐明
兼容平台 iOS 8.0+
开发环境 XCode 4.0 +
CPU 架构 armv7, arm64, i386, x86\_64
SDK 依赖 libz, libresolv, libc++ , SystemConfiguration.framework , CoreLocation.framework , CoreTelephony.framework

二、集成 SDK

2.1 下载 SDK
  • 点击下载集成 oc 版本 demo
  • 点击下载集成 swift 版本 demo

点击下载指纹 SDK,SDK 的目录构造如下:

  • dx-risk-iOS-x.x.x-xxxxxxx 目录 DXRisk sdk

    • DXRisk.framework 不带 idfa 获取逻辑的 Dynamic Library Framework
    • DXRiskWithIDFA.framework 带 idfa 获取逻辑的 Dynamic Library Framework
    • DXRiskStatic.framework 不带 idfa 获取逻辑的 Static Library Framework
    • DXRiskStaticWithIDFA.framework 带 idfa 获取逻辑的 Static Library Framework
2.2 将 SDK 接入 XCode
2.2.1 导入 Framework

DXRisk.framework,DXRiskWithIDFA.framework,DXRiskStatic.framework,DXRiskStaticWithIDFA.framework\` 其中之一间接拖入工程目录中,或者右击总文件夹增加文件。

  • 如果 App 中蕴含广告相干的性能,则抉择DXRiskWithIDFA.framework 或者 DXRiskStaticWithIDFA.framework,该版本能够提供更精准的 token
  • 如果没有广告,获取 idfa 可能导致回绝上架,此时请抉择DXRisk.framework 或者 DXRiskStatic.framework
2.2.2 增加 FrameWork 到工程

若在我的项目中增加 DXRisk.framework 或者 DXRiskWithIDFA.framework 其中之一,抉择 Target -> General,在Frameworks,Libraries,and Embedded Content 中,将 DXRisk.framework 或者DXRiskWithIDFA.framework 对应的 Embed 切换到 Embed & Sign。如下图:

若在我的项目中增加 DXRiskStatic.framework 或者 DXRiskStaticWithIDFA.framework 其中之一,须要在 Build Settings -> Other Linker Flags 设置 -ObjC 如下图:

2.2.3 配置打包脚本

以下的操作仅限导入 DXRisk.framework,DXRiskWithIDFA.framework 动静库

此步骤次要是解决上传 Store 架构不合乎的问题,如我的项目中已配置过 Carthage 或有其余相干的打包 Framework 调整脚本,可略过此步自行调整 抉择 Target -> Build Phases,点击+ 按钮,增加如下脚本:


APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"

# This script loops through the frameworks embedded in the application and
# removes unused architectures.
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"

EXTRACTED_ARCHS=()

for ARCH in $ARCHS
do
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
done

echo "Merging extracted architectures: ${ARCHS}"
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
rm "${EXTRACTED_ARCHS[@]}"

echo "Replacing original executable with thinned version"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"

done
2.2.4 权限留神

在 iOS 12 的环境最好在 Capabilities->Access WiFi Information 进行开启操作,这样不便设施指纹数据采集。

三、接口应用阐明

3.1 办法和参数阐明
// 风控组件:DXRiskManager 类
@interface DXRiskManager : NSObject

// 字符串常量
extern NSString* const DXRiskManagerKeyUserId;
extern NSString* const DXRiskManagerKeyEmail;
extern NSString* const DXRiskManagerKeyPhone;
extern NSString* const DXRiskManagerKeyUserExtend1;
extern NSString* const DXRiskManagerKeyUserExtend2;
extern NSString* const DXRiskManagerKeyURL;// 私有化服务器地址
extern NSString* const DXRiskManagerKeyBackup;// 私有化下应用,将数据备份到顶象服务器(开启为 DXRiskManagerKeyBackupEnable 值)extern NSString* const DXRiskManagerKeyBackupAppId; // 私有化下应用,指定数据备份到顶象服务器的 AppId 
  
extern NSString* const DXRiskManagerKeyDegradeNotify;// 数据降级告诉,若关上,服务端会有响应的降级统计
extern NSString* const DXRiskManagerKeyCountry;// 国家地区设置,默认中国

extern NSString* const DXRiskManagerKeyDelayMsTime; // 可填设置申请超时毫秒工夫(默认值为 500,范畴是:【100:3000】)// NoticeDegrade 参数
/* The NoticeDegrade Value. This value only be used pair with key:DXRiskManagerKeyDegradeNotify to notify token degrade. */
extern NSString* const DXRiskManagerKeyDegradeNotifyEnable;
// Backup 参数
/* The Backup Value. This value only be used pair with key:DXRiskManagerKeyBackup to set data backup. */
extern NSString* const DXRiskManagerKeyBackupEnable;
// Country 参数
/* The Country Value. This value only be used pair with key:DXRiskManagerKeyCountry to set country. */
extern NSString* const DXRiskManagerCountryChina;
/* The Country Value. This value only be used pair with key:DXRiskManagerKeyCountry to set country. */
extern NSString* const DXRiskManagerCountryIndonesia;

/**
 采集端的设施指纹信息,上传至风控后盾,再由风控后盾返回 token。该 API 为耗时操作,因而必须在非主线程上调用。@param appId appId   开明服务后可在二级菜单“利用治理”中获取
 @param extendsParams 配置项
 @return token
 */
+ (NSString *)getToken:(NSString *)appId extendParams:(NSDictionary *)extendsParams;

/** 
 DXRiskManager -- 初始化办法
 */
+ (BOOL)setup;  
@end
3.2 应用示例
// 整个过程因为是耗时操作,必须要在非主线程上执行,否则会阻塞 UI。如果自身曾经在非 UI 线程上执行,则不须要另开线程
    dispatch_queue_t dxrisk_queue = dispatch_queue_create("com.dingxiang.dxrisk", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(dxrisk_queue, ^{NSMutableDictionary *dic = [NSMutableDictionary dictionary];
        // 依据业务逻辑,填充自定义字段
        [dic setObject:@"123456" forKey:DXRiskManagerKeyUserId];
      
        // 如需设置海内服务器, 可选值请参考头文件字段
        [dic setObject:DXRiskManagerServiceAreaSoutheastAsia forKey:DXRiskManagerKeyServiceArea];
        // 如需自定义服务端 URL,填充 DXRiskManagerKeyURL 字段(私有化部署的状况)// 如有须要则增加 DXRiskManagerKeyBackup 参数,Value 固定为 DXRiskManagerKeyBackupEnable
        // DXRiskManagerKeyBackupAppId 参数可不填,参数为顶象备份数据库提供的备份 Appid
        [dic setObject:@"http://xxxxxxx" forKey:DXRiskManagerKeyURL];
        // [dic setObject:DXRiskManagerKeyBackupEnable forKey:DXRiskManagerKeyBackup];
        [dic setObject:@"xxxxxxxxxxxxxxxxxxxx" forKey:DXRiskManagerKeyBackupAppId];
        // 此配置敞开 SDK 缓存,示意每次调用接口都强制采集信息
        // [dic setObject:@"clear" forKey:@"PRIVATE_CLEAR_TOKEN"];
        
        // 获取 token
        // 留神:token 最好不要保留在某个局部变量或者字段,每次应用时,都通过 API 获取。BOOL isSuccess = [DXRiskManager setup];
        NSLog(@"setup success: %@" , isSuccess ? @"YES":@"NO");
        NSString *constID = [DXRiskManager getToken:@"xxxxxxxxxxxxxxxxxxxx" extendsParams:dic];
        NSLog(@"constID: %@", constID);
        // TODO 把 constid 通过 Post 申请,传到业务后盾。// 上面是模仿频繁调用的过程
        while(TRUE) {NSLog(@"constID: %@", [DXRiskManager getToken:@"xxxxxxxxxxxxxxxxxxxx" extendsParams:dic]);
            [NSThread sleepForTimeInterval:.5];
        }
    });
3.3 异样阐明

在获取 token 过程中,如果因为网络超时或者加解密失败,该接口有可能会返回为 null,同时会输入 tag 为 DXRISK 的错误信息,具体形容如下:

DXRISK_REQUEST_NETWORK_ERR            -1001         // 网络链接失败
DXRISK_REQUEST_DECRYPT_ERR            -1002         // 数据解密谬误
DXRISK_REQUEST_UNCOMPRESS_ERR         -1003         // 解压谬误
DXRISK_REQUEST_RESPONSE_EMPTY_ERR     -1004         // 返回为空
DXRISK_REQUEST_DATA_PARSE_ERR         -1005         // 数据解析失败
DXRISK_REQUEST_DIRTY_DATA_ERR         -1006         // 脏数据
DXRISK_CONST_ID_EMPTY                 -1007         //constid 为空

微信小程序接入

js 接入

一、下载设施指纹 js

SaaS 版本下载

私有化版本下载

请留神抉择对应的版本,下载实现后放到本地我的项目中。

二、获取密钥

未注册用户可在顶象官网进行账号注册,创立利用获取利用密钥 AppID 和 AppSecret。

三、应用

  1. 代码接入

<!—->

const ConstId = require('本地设施指纹 js 寄存门路')
Page({onLoad: function () {
      new ConstId({
        appId: '【这里填写在顶象官网申请到的 AppID】', // 惟一标识,必填
        server: 'https://host/udid/w1' // 服务接口地址,请留神私有化客户填写自有域名
      }, (e, id) => {if (e) {console.log(e)
          return
        }
        console.log('constId:', id)
      })
    }
})
  1. SaaS 用户在小程序后盾配置业务域名https://constid.dingxiang-inc.com,私有化用户配置本地部署域名,测试阶段能够开启微信开发者工具右上角详情 -> 本地设置 ->“不校验域名”。

支付宝小程序接入

接入形式和微信小程序相似,然而应用的 SDK 不一样。如有须要,请分割客服获取。

const ConstId = require('本地设施指纹 js 寄存门路')
Page({onLoad: function () {
      new ConstId({
        appId: '【这里填写在顶象官网申请到的 AppID】', // 惟一标识,必填
        server: 'https://host/udid/w1' // 服务接口地址,请留神私有化客户填写自有域名
      }, (e, id) => {if (e) {console.log(e)
          return
        }
        console.log('constId:', id)
      })
    }
})

以上。

如果有设施指纹需要的话,能够返回顶象:收费试用

退出移动版