設(shè)備風(fēng)險SDK iOS接入
本文介紹了阿里云設(shè)備指紋iOS SDK接入流程。
前提條件
設(shè)備風(fēng)險SDK需在iOS 9.0及以上的系統(tǒng)版本上運行。
合規(guī)條款
1、您需要確保App有《風(fēng)險識別SDK隱私權(quán)政策》,并且在用戶首次啟動App時就彈出《風(fēng)險識別SDK隱私權(quán)政策》取得用戶同意,請勿默認客戶已勾選。
2、您務(wù)必在《風(fēng)險識別SDK隱私權(quán)政策》中向用戶告知使用阿里云設(shè)備風(fēng)險識別SDK,參考條款如下:
使用SDK名稱:阿里云設(shè)備風(fēng)險識別SDK;
服務(wù)類型:檢測篡改設(shè)備、模擬器、惡意腳本等異常設(shè)備;
收集設(shè)備信息:當(dāng)您使用風(fēng)險識別產(chǎn)品且接入設(shè)備風(fēng)險識別SDK服務(wù)時,為了檢測最終用戶的設(shè)備欺詐與作弊行為,識別設(shè)備的真實性,我們會獲取最終用戶的:
設(shè)備基礎(chǔ)信息:設(shè)備制造商、設(shè)備品牌、設(shè)備類型及型號、設(shè)備名稱、設(shè)備操作系統(tǒng)信息、設(shè)備內(nèi)存及存儲大小、傳感器列表、電池及電量信息、基帶信息、開機時間、屏幕亮度及分辨率、CPU信息、系統(tǒng)時區(qū)、系統(tǒng)語言、充電狀態(tài)、系統(tǒng)內(nèi)核信息;
設(shè)備標(biāo)識信息(必要):IDFV;
設(shè)備標(biāo)識信息(可選):IMEI(國際移動識別碼)、IMSI(國際移動用戶識別碼)、MAC地址、ICCID(集成電路卡識別碼)、硬件序列號、IDFA、Android ID、OAID、Google AID(Google廣告ID)、藍牙MAC;
設(shè)備網(wǎng)絡(luò)信息:IP地址(可選)、附近WIFI列表(可選)、BSSID(可選)、SSID(可選)、運營商信息、網(wǎng)絡(luò)類型、網(wǎng)絡(luò)狀態(tài)、SIM卡狀態(tài)、網(wǎng)卡信息;
設(shè)備應(yīng)用信息:SDK宿主APP信息(包括:應(yīng)用名稱、應(yīng)用版本、安裝時間)、應(yīng)用列表(可選)。
隱私政策鏈接:《風(fēng)險識別SDK隱私權(quán)政策》。
3、您務(wù)必確保用戶同意《風(fēng)險識別SDK隱私權(quán)政策》之后,再使用阿里云設(shè)備風(fēng)險識別SDK采集信息。如無必要,請勿在啟動應(yīng)用時采集設(shè)備信息,避免過度或過早采集。
權(quán)限說明
為增強風(fēng)險識別效果,在App Store上架之前,請確認App已經(jīng)在Info.plist
中添加如下字段及說明信息,否則可能會導(dǎo)致上架失敗。
權(quán)限 | 是否必選 | 備注 |
NSLocalNetworkUsageDescription | 否(推薦賦予) | 獲取局域網(wǎng)內(nèi)設(shè)備連通性,用于發(fā)現(xiàn)設(shè)備牧場、群控等風(fēng)險。 |
NSUserTrackingUsageDescription | 否 | 用于獲取IDFA信息,增強設(shè)備ID穩(wěn)定性。 |
下載及配置SDK
1、下載iOS SDK(SDK為XCode上標(biāo)準(zhǔn)靜態(tài)framework包),并在下載SDK的控制臺中生成AppKey。
2、將SDK包中的deviceiOS.framework復(fù)制到iOS工程目錄下。
3、選擇工程配置,定位到Build Phases -> Link Binary With Libraries,添加deviceiOS.framework及其依賴包:
AppTrackingTransparency.framework
CoreTelephony.framework
libresolv.tbd
Security.framework
AdSupport.framework
libz.tbd
libc++.tbd
deviceiOS.framework
4、下載Objective-C Demo包。(單擊 ,安卓:A.demo,iOS:I.demo)。
5、請根據(jù)自身業(yè)務(wù)屬性,選擇是否帶有idfa
等敏感數(shù)據(jù)采集功能的SDK,具體參考SDK下載列表描述。
通過SDK采集數(shù)據(jù)
通過SDK采集數(shù)據(jù),務(wù)必確保用戶同意《風(fēng)險識別SDK隱私權(quán)政策》之后,在風(fēng)險場景盡早通過阿里云設(shè)備風(fēng)險識別SDK采集數(shù)據(jù)。
函數(shù)原型
@interface SecurityDevice : NSObject
- (void)initDevice:(NSString *)userAppKey
withOptions:(NSMutableDictionary *)options
callback:(void (^)(int))initCallback;
// ...
@end
參數(shù)
userAppKey:用于標(biāo)識用戶身份,可在阿里云控制臺的設(shè)備App管理申請獲取。
options:采集數(shù)據(jù)的可選項,默認可以為
nil
。可選參數(shù)如下:
字段名 | 說明 | 示例 |
IPv6 | 是否使用IPv6域名上報設(shè)備信息。 默認為“0”:使用IPv4域名; “1”:使用IPv6域名。 | "1" |
CustomUrl | 設(shè)置自有數(shù)據(jù)上報服務(wù)器域名 | "https://cloudauth-device.aliyuncs.com" |
CustomHost | 設(shè)置自有數(shù)據(jù)上報服務(wù)器host | "cloudauth-device.aliyuncs.com" |
initCallback:設(shè)備風(fēng)險SDK采集數(shù)據(jù)回調(diào)接口,可在回調(diào)中判斷采集數(shù)據(jù)是否成功。其中,Code
字段取值范圍可參考“狀態(tài)返回值”。
返回值:無。
當(dāng)initCallback回調(diào)的Code
值返回不為10000的時候,可以在App后續(xù)的邏輯中重新調(diào)用initDevice接口進行數(shù)據(jù)采集,直到成功為止。
獲取客戶端Token
獲取客戶端Token,并上報到業(yè)務(wù)服務(wù)器,后續(xù)通過服務(wù)器端設(shè)備風(fēng)險識別事件及返回參數(shù),從而獲取設(shè)備風(fēng)險信息。
函數(shù)原型
@interface SecurityDevice : NSObject
// ...
- (SecurityToken *) getDeviceToken;
@end
參數(shù):無。
返回值:SecurityToken類型。
Code
:返回接口調(diào)用狀態(tài)碼,可用于判斷接口調(diào)用是否成功。Code
字段取值范圍可參考“狀態(tài)返回值”。Token
:返回客戶端Token
字符串信息,可用于業(yè)務(wù)后續(xù)查詢阿里云設(shè)備風(fēng)險識別接口。
@interface SecurityToken : NSObject
// 獲取 token 操作的結(jié)果
@property(atomic) int code;
// token 字符串
@property(copy, atomic) NSString *token;
@end
Token
獲取時機建議:
1、在initDevice接口的callback返回10000的時候獲取;
2、如果不等待initDevice的callback返回,我們建議initDevice接口和getDeviceToken接口口調(diào)用時間能間隔2秒以上;(因為數(shù)據(jù)上報可能存在延遲)
3、每次在需要風(fēng)險查詢的時候,重新獲取Token
,Token
的有效期為7天。
狀態(tài)返回值
Code | 說明 |
10000 | SDK采集數(shù)據(jù)成功。 |
10001 | SDK未采集數(shù)據(jù)。 |
10002 | SDK需要的基礎(chǔ)權(quán)限未完全授權(quán)。 |
10003 | 系統(tǒng)未知錯誤。 |
10004 | 網(wǎng)絡(luò)錯誤。 |
10005 | 網(wǎng)絡(luò)錯誤,返回內(nèi)容為空串。 |
10006 | 網(wǎng)絡(luò)返回的格式非法。 |
10007 | 服務(wù)端配置解析失敗。 |
10008 | 內(nèi)部采集數(shù)據(jù)未完成。 |
示例代碼
設(shè)備風(fēng)險識別SDK采集數(shù)據(jù),initDevice接口需要在各種風(fēng)險場景中盡可能早的時候調(diào)用。
根據(jù)蘋果官方隱私政策規(guī)定,IDFA的使用除了在plist
中做相關(guān)說明之后,需要調(diào)用方主動彈框提示用戶授權(quán),因此開發(fā)環(huán)境需要確保是Xcode 12以上。
typedef void (^IDFARequestBlock)(bool success);
API_AVAILABLE(ios(14))
static bool isATTrackingEnabled(ATTrackingManagerAuthorizationStatus status) {
if (ATTrackingManagerAuthorizationStatusAuthorized == status) {
return true;
}
return false;
}
- (void)helperRequestIDFAPermissionWithBlock:(IDFARequestBlock) complete {
if (@available(iOS 14, *)) {
ATTrackingManagerAuthorizationStatus authStatus = ATTrackingManager.trackingAuthorizationStatus;
if (ATTrackingManagerAuthorizationStatusNotDetermined == authStatus) {
[ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
if (nil != complete) {
return complete(isATTrackingEnabled(status));
}
}];
} else if (nil != complete) {
return complete(isATTrackingEnabled(authStatus));
}
}
}
- (void)initSecurityDevice {
SecurityDevice *securityDevice = [SecurityDevice sharedInstance];
[securityDevice initDevice: @ "ALIYUN_APPKEY": ^ (int code) {
NSString * initResult = [NSString stringWithFormat: @ "init code: %d", code];
NSLog(@ "%@", initResult);
if (10000 != code) {
NSLog(@ "init error.");
} else {
NSLog(@ "init success");
}
}];
}
- (void)viewDidLoad {
[super viewDidLoad];
// iOS 14及以上系統(tǒng)需要用戶彈框獲取 IDFA 權(quán)限。
if (@available(iOS 14, *)) {
[self helperRequestIDFAPermissionWithBlock:^(bool success) {
if (success) {
NSLog(@"IDFA Permission OK.");
} else {
NSLog(@"No IDFA Permission.");
}
[self initSecurityDevice];
}];
} else {
[self initSecurityDevice];
}
}
在業(yè)務(wù)需要風(fēng)險識別的場景下(如注冊、活動推廣等)獲取戶端Token
,并上報到業(yè)務(wù)的服務(wù)器端進行風(fēng)險查詢。
SecurityDevice *securityDevice = [SecurityDevice sharedInstance];
SecurityToken * deviceToken = [securityDevice getDeviceToken];
NSString * rs = [NSString stringWithFormat: @ "[%d]%@", deviceToken.code, deviceToken.token];
NSLog(@ "deviceToken: %@", rs);
// 發(fā)送token到業(yè)務(wù)自有服務(wù)器并查詢阿里云設(shè)備風(fēng)險識別接口。
// ...
調(diào)用風(fēng)險識別API接口
將deviceToken
與其他參數(shù),根據(jù)如下相應(yīng)的風(fēng)險識別服務(wù)事件參數(shù)文檔說明,請求風(fēng)險識別API接口進行識別: