前言
iOS11 苹果改动了一个比较引开发者关注的亮点
UDID之类的写到系统 keychain 的唯一标识会随着 app 删除而删除
这个问题在微博上已经争论好几天
iOS11新的设备唯一标识 DCDevice
介绍 API
我们首先看看DCDevice
类都有啥
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#import <DeviceCheck/DeviceCheck.h>
NS_ASSUME_NONNULL_BEGIN
API_AVAILABLE(ios(11.0), tvos(11.0)) API_UNAVAILABLE(watchos, macos)
@interface DCDevice : NSObject
//当前设备
@property (class, readonly) DCDevice *currentDevice;
//是否支持
@property (getter=isSupported, readonly) BOOL supported;
//生成唯一标识的 token 注意:每call一次就会生成一个新的 token(和前边不同)
- (void)generateTokenWithCompletionHandler:(void(^)(NSData * _Nullable token, NSError * _Nullable error))completion;
@end
NS_ASSUME_NONNULL_END
接口简直不能再简单了 创建实例调方法
使用 API
下面我们来看下如何使用DCDevice
导入头文件
1
#import <DeviceCheck/DeviceCheck.h>
check 是否支持 如果支持 的话会在回调以后返回 token
(NSData)
1
2
3
4
5
6
7
8
9
10
11
- (void)viewDidLoad {
[super viewDidLoad];
//下面是调用代码
if([DCDevice currentDevice].supported){
[[DCDevice currentDevice] generateTokenWithCompletionHandler:^(NSData * _Nullable token, NSError * _Nullable error) {
NSLog(@"%@",token);
}];
}
}
token 是个 2188字节(2k 多点)的二进制流,很小
我尝试各种字符串编码最终也不知道里面是啥 没能成功打印出来
谁要是打印出来烦请 share 一下
删除/重装App 如何处理
DeviceCheck 允许你通过你的服务器与 Apple 服务器通讯,并为单个设备设置2k左右 的数据。 在设备上用 DeviceCheck API 生成一个 2字节的 token (00, 01,10,11),然后将这个 token 发给自己的服务器,再由自己的服务器与 Apple 的 API 进行通讯,来更新或者查询该设备的值。这两字节 的数据用来追踪用户。比如。借助两个自己的数据,你可以得知用户究竟使用了该 App 多久。 该 API 可以成为:反欺诈领域: 试用7天 Uber、滴滴司机被封号后,防止重新注册账号接单 该用户是否已经领取过首次注册红包 APP防多开 因为传输的是 flag 级别的数据,并不会定位到该设备的使用者,所以相对安全。
但是对于购买了二手手机的使用场景,可能会出现一些边界情况,这个在业务中也需要考虑进去。
首先要明白我们 的 token 需要发给谁
- token 需要发送给我们自己公司的
server
做记录 - 我们公司自己的
server
去Apple
的server
查询token
是否有效,从而来更新或者查询该设备值. - 这
2k 左右的 token
不会因为设备删除 app 而删除 会一直存在苹果的 server(其实我觉得就是苹果自己去获取的设备唯一标识).
那么 怎么查询和更新呢
查询接口
https://api.development.devicecheck.apple.com/v1/query_two_bits
可以用终端自己模拟一下 就当作你自己是自己的服务器访问Apple 的服务器
1
2
3
4
curl -i --verbose -H "Authorization: Bearer <GeneratedJWT>" \
-X POST --data-binary @ValidQueryRequest.json \
https://api.development.devicecheck.apple.com/v1/query_two_bits
json 的定义如下:
字段 key | 类型 | 说明 | 必须 |
---|---|---|---|
device_token | String | 设备唯一标识 token | 是 |
transaction_id | String | 服务器产生的一个ID | 是 |
timestamp | Long | 服务器生成的UTC时间戳 | 是 |
它会 返回 如下格式
1
2
3
4
5
{
"device_token" : "wlkCDA2Hy/CfrMqVAShs1BAR/0sAiuRIUm5jQg0a..."
"transaction_id" : "5b737ca6-a4c7-488e-b928-8452960c4be9",
"timestamp" : 1487716472000
}
更新接口
https://api.development.devicecheck.apple.com/v1/update_two_bits
1
2
3
curl -i --verbose -H "Authorization: Bearer <GeneratedJWT>" \
-X POST --data-binary @ValidUpdateRequest.json \
https://api.development.devicecheck.apple.com/v1/update_two_bits
json 的定义如下:
字段 key | 类型 | 说明 | 必须 |
---|---|---|---|
device_token | String | 设备唯一标识 token | 是 |
transaction_id | String | 服务器产生的一个ID | 是 |
timestamp | Long | 服务器生成的UTC时间戳 | 是 |
bit0 | Boolean | 新的布尔值1 | 否 |
bit1 | Boolean | 新的布尔值2 | 否 |
json 的示例:
1
2
3
4
5
6
7
{
"device_token" : "wlkCDA2Hy/CfrMqVAShs1BAR/0sAiuRIUm5jQg0a..."
"transaction_id" : "5b737ca6-a4c7-488e-b928-8452960c4be9",
"timestamp" : 1487716472000,
"bit0" : true,
"bit1" : false
}
最终的方案
- iOS11以前版本暂且才用 UUID 等 keychian 方式
- iOS11尽量才用新的 api 来适配解决
对于 server 来讲可以 把 token 搞成新的附属字段 比如一个账号下登录多少个设备
那么 一个 UID 下面 就要附属 iOS 版本+ token
相信过不了多久 很成熟的 token方案会脱颖而出
如果本文有误之处还请各路大神指教
全文完