若汐妈妈 發表於 2019-11-6 16:51:00

iOS开发高级分享 - iOS上的设备标识符和指纹

<h1>苹果认可的标识符</h1>
<p>Apple提供了各种API,以方便用户识别各种用途:</p>
<h1>通用标识符(UDID)</h1>
<p>在iOS的早期,苹果公司提供了一个uniqueIdentifier财产上UIDevice-亲切地称为udid (不要与UUID混淆)。虽然这样的功能在今天看来是不可想象的,但该属性一直存在到IOS 5,直到它被废弃并被替换为identifierForVendor在iOS 6中。</p>
<h1>供应商标识符(IDFV)</h1>
<p>从IOS 6开始,开发人员可以使用identifierForVendor财产上UIDevice若要生成在同一供应商创建的应用程序和扩展之间共享的唯一标识符(idfv).</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">import UIKit
let idfv </span>= UIDevice.current.identifierForVendor <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> BD43813E-CFC5-4EEB-ABE2-94562A6E76CA</span></pre>
</div>
<blockquote>
<p>根据文献 identifierForVendor回归nil“在重新启动设备之后,但在用户解锁设备之前。”目前还不清楚什么时候会出现这种情况,但是如果你的应用程序在后台做了什么事情,一定要记住一些事情。</p>
</blockquote>
<h1>广告标识符(IDFA)</h1>
<p>连同identifierForVendor引进了一种新的行政支助框架,这是苹果创建的,以帮助区分应用程序功能所需的识别功能与任何服务于广告的东西。</p>
<p>结果advertisingidentifier财产(亲切地称为idfa(由其同伙)不同于identifierForVendor通过为每个人返回相同的值。值可以更改,例如,如果用户重置广告标识符或者抹去他们的设备。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">import AdSupport
let idfa </span>= ASIdentifierManager.shared().advertisingIdentifier</pre>
</div>
<p><br>如果广告跟踪受到限制,则该属性将返回一个归零UUID。</p>
<div class="cnblogs_code">
<pre>idfa.uuidString == <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">00000000-0000-0000-0000-000000000000</span><span style="color: rgba(128, 0, 0, 1)">"</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> true if the user has limited ad tracking</span></pre>
</div>
<blockquote>
<p>奇怪的是,MacOS Mojave引入了一个clearAdvertisingIdentifier()方法,它似乎会创建一个“公地悲剧”在这种情况下,一个应用程序可能会破坏其他人的利益。(从用户的角度来看,这不是一件坏事!)</p>
<p>还有一个奇怪的例子isAdvertisingTrackingEnabled财产。根据文献:<br>在执行任何广告跟踪之前,请检查此属性的值。如果值为false,则只将广告标识符用于以下目的:频率限制、属性、转换事件、估计唯一用户的数量、广告欺诈检测和调试。<br>这种“荣誉制度”方法遵从性令人困惑。这让你想知道是什么用法不会属于这些广泛的津贴范围之内。<br>如果你对这件事的警力有任何洞察力,给我们一条线-我们想听更多.</p>
</blockquote>
<h1>&nbsp;DeviceCheck</h1>
<p>identifierForVendor和advertisingIdentifier提供与uniqueIdentifier属性在IOS 6中替换,只有一个例外:能够在设备重置和应用程序卸载过程中持久化。</p>
<p>在iOS 11中,苹果悄悄地推出了DeviceCheck框架,它允许开发人员分配由Apple持久化的两位信息直到开发人员手动删除.</p>
<p>任何熟悉DeviceCheck框架的人都应该熟悉与DeviceCheck框架的交互APN在App Store Connect和您的服务器上设置设备之后,客户端在设备上生成令牌,这些令牌被发送到服务器以设置或查询两位信息:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">import DeviceCheck

let device </span>=<span style="color: rgba(0, 0, 0, 1)"> DCDevice.current
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> device.isSupported {
device.generateToken { data, error </span><span style="color: rgba(0, 0, 255, 1)">in</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> let token = data?<span style="color: rgba(0, 0, 0, 1)">.base64EncodedString() {
send token to your server
}
}
}</span></pre>
</div>
<p>基于设备令牌和客户端发送的其他信息,服务器告诉Apple通过发送如下JSON有效负载来设置每个位值:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">device_token</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">QTk4QkFDNEItNTBDMy00Qjc5LThBRUEtMDQ5RTQzRjNGQzU0Cg==</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">transaction_id</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">D98BA630-E225-4A2F-AFEC-BE3A3D591708</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">timestamp</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">1572531720</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">bit0</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">bit1</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
}</span></pre>
</div>
<p><br>为了在稍后的时间点检索这两位,服务器发送一个没有bit0和bit1字段:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">device_token</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">QTk4QkFDNEItNTBDMy00Qjc5LThBRUEtMDQ5RTQzRjNGQzU0Cg==</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">transaction_id</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">D98BA630-E225-4A2F-AFEC-BE3A3D591708</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">timestamp</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">1572532500</span><span style="color: rgba(0, 0, 0, 1)">
}</span></pre>
</div>
<p>如果一切正常,苹果的服务器将以200状态代码和以下JSON有效负载:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">bit0</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(0, 0, 255, 1)">true</span>
<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">bit1</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">last_update_time</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">2019-10</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
}</span></pre>
</div>
<blockquote>
<p>据称,苹果创建了DeviceCheck框架,以满足优步在限制滥用促销代码方面的需求。虽然DeviceCheck支持存储只两位信息(例如,足以确定设备是否曾被用于创建帐户以及设备是否与欺诈活动相关联),我们(诚然是模糊的)担心时间戳,即使是截断,也可能被用来存储两位以上的信息。</p>
</blockquote>
<h1>今日iOS的指纹图谱</h1>
<p>尽管苹果提供了这些服务,但广告商仍在继续努力规避用户隐私保护,并利用他们掌握的所有信息,以其他方式识别用户。</p>
<p>多年来,苹果对设备硬件信息的访问受到限制,已安装的应用程序, 附近WiFi网络...他们要求应用程序请求许可才能获得您当前的位置,访问您的相机和麦克风,浏览您的联系人,并找到并连接到蓝牙附件。他们采取了大胆的步骤防止Safari中的用户跟踪.</p>
<p>由于缺乏这方面的信息,公司不得不发挥创造力,从现有信息的残余物中提炼出独特的身份。这种由外部因素组合而成的识别过程称为指印.</p>
<p>不幸的现实是,我们可以通过微不足道的少量信息得到独特的识别。例如,一个群体中的个体最多可以被四个时间戳坐标所挑选出来。(de Montjoye,Hidalgo,Verleysen,&amp;Blondel,2013年)或者仅仅是生日和邮政编码(Sweeney,2000年).</p>
<p>自2012年以来,每个WWDC都举办了一次关于隐私的会议,但唯一特别提到指纹的是2014年的简短讨论如何避免这样做。</p>
<p>根据我们的计算,坚定的一方可以使用传统的、不受限制的API来产生几十个随机性:</p>
<p><strong>地区信息(~36位)</strong><br>地区信息是在苹果平台上识别信息的最大来源。你喜欢的语言、区域、日历、时区的组合,以及你安装的键盘很大程度上说明了你是谁--尤其是在你没有那么传统的偏好的情况下。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">import Foundation

Locale.current.languageCode
log2(Double(Locale.isoLanguageCodes.count)) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 9.217 bits</span>
<span style="color: rgba(0, 0, 0, 1)">
Locale.current.regionCode
log2(Double(Locale.isoRegionCodes.count)) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 8 bits</span>
<span style="color: rgba(0, 0, 0, 1)">
Locale.current.calendar.identifier
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ~2^4 (16) Calendars</span>
<span style="color: rgba(0, 0, 0, 1)">
TimeZone.current.identifier
log2(Double(TimeZone.knownTimeZoneIdentifiers.count)) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 8.775 bits</span>
<span style="color: rgba(0, 0, 0, 1)">
UserDefaults.standard.</span><span style="color: rgba(0, 0, 255, 1)">object</span>(forKey: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">AppleKeyboards</span><span style="color: rgba(128, 0, 0, 1)">"</span>)<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ~2^6 (64) iOS keyboards</span></pre>
</div>   
<blockquote>
<p>我们最近推特关于可以不受限制地访问表情符号键盘信息的应用程序。从那时起,我们就被告知苹果公司正在调查这一问题。</p>
</blockquote>
<p><strong>可访问性(~10位)</strong><br>可访问性首选项还提供了大量的信息,每个单独的设置都贡献了一个潜在的比特:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">UIAccessibility.isBoldTextEnabled
UIAccessibility.isShakeToUndoEnabled
UIAccessibility.isReduceMotionEnabled
UIAccessibility.isDarkerSystemColorsEnabled
UIAccessibility.isReduceTransparencyEnabled
UIAccessibility.isAssistiveTouchRunning</span></pre>
</div>
<p><br>约25%的用户利用动态类型通过配置首选字体大小,该选择还可用于指纹:</p>
<div class="cnblogs_code">
<pre>let application =<span style="color: rgba(0, 0, 0, 1)"> UIApplication.shared
application.preferredContentSizeCategory</span></pre>
</div>
<p><br><strong>硬件信息(~5或~6位)</strong><br>尽管这些年来,操作系统更新中大多数最活跃的比特都被锁定了,但仍然有足够多的比特用于识别。</p>
<p>在IOS上,您可以获得用户设备的当前模型和存储量:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">import UIKit

let device </span>=<span style="color: rgba(0, 0, 0, 1)"> UIDevice.current
device.name </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> "iPhone 11 Pro"</span>
<span style="color: rgba(0, 0, 0, 1)">
let fileManager </span>= FileManager.<span style="color: rgba(0, 0, 255, 1)">default</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> let path = fileManager.urls(<span style="color: rgba(0, 0, 255, 1)">for</span>: .libraryDirectory, <span style="color: rgba(0, 0, 255, 1)">in</span>: .systemDomainMask).last?<span style="color: rgba(0, 0, 0, 1)">.path,
let systemSize </span>= <span style="color: rgba(0, 0, 255, 1)">try</span>? fileManager.attributesOfFileSystem(forPath: path)[.systemSize] <span style="color: rgba(0, 0, 255, 1)">as</span>?<span style="color: rgba(0, 0, 0, 1)"> Int
{
Measurement</span>&lt;UnitInformationStorage&gt;<span style="color: rgba(0, 0, 0, 1)">(value: Double(systemSize), unit: .bytes)
.converted(to: .gigabytes) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ~256GB</span>
}</pre>
</div>
<p>带着14个支持的IOS设备,大多数都有3种配置,假设这贡献了大约32种可能性,或者说是5位。</p>
<p>您可以在MacOS上更进一步,通过处理器计数和RAM数量来进一步区分硬件:</p>
<div class="cnblogs_code">
<pre>processInfo.processorCount <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 8</span>
<span style="color: rgba(0, 0, 0, 1)">
Measurement</span>&lt;UnitInformationStorage&gt;<span style="color: rgba(0, 0, 0, 1)">(value: Double(processInfo.physicalMemory),
unit: .bytes)
.converted(to: .gigabytes) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 16GB</span></pre>
</div>
<p>很难感觉到有多少种不同的mac型号在使用?,但是一个合理的估计大概是2。6或27.</p>
<p><strong>&nbsp;蜂窝网络(~2比特)</strong><br>知道某人的手机是在威瑞森还是沃达丰,也可以被考虑到指纹。您可以使用CTTelephonyNetworkInfo类的CoreTelephone框架若要查找具有蜂窝服务的设备的提供程序,请执行以下操作:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">import CoreTelephony

let networkInfo </span>=<span style="color: rgba(0, 0, 0, 1)"> CTTelephonyNetworkInfo()
let carriers </span>= networkInfo.serviceSubscriberCellularProviders?<span style="color: rgba(0, 0, 0, 1)">.values
carriers</span>?.map { ($<span style="color: rgba(128, 0, 128, 1)">0</span>.mobileNetworkCode, $<span style="color: rgba(128, 0, 128, 1)">0</span>.mobileCountryCode) }</pre>
</div>
<p>每个国家的供应商数量各不相同,但以美国的4家主要运营商为指导,我们可以说,运营商信息将贡献约2位(如果您安装了多个SIM卡,则贡献更多)。</p>
<p><strong>通信首选项(2位)</strong><br>更普遍的是,即使知道某人是否可以发送短信或电子邮件,也可以被考虑到指纹中。可以在没有权限的情况下通过MessageUI框架.</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">import MessageUI

MFMailComposeViewController.canSendMail()
MFMessageComposeViewController.canSendText()</span></pre>
</div>
<p><strong>识别信息的其他来源</strong><br>如果数字指纹的使用看起来很奇怪的话,那只是触及了公司和研究人员如何绕过你的隐私的表面而已。</p>
<p><strong>&nbsp;GeoIP与相关网络速度</strong><br>虽然通过传统的API访问地理位置需要明确的授权,但是第三方可能能够根据访问Internet的方式对您所处的世界的位置有一个大致的了解。</p>
<p>按源IP地址定位广泛用于区域锁定和本地化。您还可以将此信息与平时测量到已知位置的主机,以便更准确地定位位置。(Weinberg,Cho,Christin,Sekar,&amp;Gill,2018):</p>
<div class="cnblogs_code">
<pre>ping -c <span style="color: rgba(128, 0, 128, 1)">5</span> <span style="color: rgba(128, 0, 128, 1)">99.24</span>.<span style="color: rgba(128, 0, 128, 1)">18.13</span><span style="color: rgba(0, 0, 0, 1)"> # San Francisco, USA

</span>--- <span style="color: rgba(128, 0, 128, 1)">99.24</span>.<span style="color: rgba(128, 0, 128, 1)">18.13</span> ping statistics ---
<span style="color: rgba(128, 0, 128, 1)">5</span> packets transmitted, <span style="color: rgba(128, 0, 128, 1)">5</span> packets received, <span style="color: rgba(128, 0, 128, 1)">0.0</span>%<span style="color: rgba(0, 0, 0, 1)"> packet loss
round</span>-trip min/avg/max/stddev = <span style="color: rgba(128, 0, 128, 1)">11.900</span>/<span style="color: rgba(128, 0, 128, 1)">12.184</span>/<span style="color: rgba(128, 0, 128, 1)">12.895</span>/<span style="color: rgba(128, 0, 128, 1)">0.380</span><span style="color: rgba(0, 0, 0, 1)"> ms

ping </span>-c <span style="color: rgba(128, 0, 128, 1)">5</span> <span style="color: rgba(128, 0, 128, 1)">203.47</span>.<span style="color: rgba(128, 0, 128, 1)">10.37</span><span style="color: rgba(0, 0, 0, 1)"> # Adelaide, Australia

</span>--- <span style="color: rgba(128, 0, 128, 1)">203.47</span>.<span style="color: rgba(128, 0, 128, 1)">10.37</span> ping statistics ---
<span style="color: rgba(128, 0, 128, 1)">5</span> packets transmitted, <span style="color: rgba(128, 0, 128, 1)">5</span> packets received, <span style="color: rgba(128, 0, 128, 1)">0.0</span>%<span style="color: rgba(0, 0, 0, 1)"> packet loss
round</span>-trip min/avg/max/stddev = <span style="color: rgba(128, 0, 128, 1)">202.122</span>/<span style="color: rgba(128, 0, 128, 1)">202.433</span>/<span style="color: rgba(128, 0, 128, 1)">203.436</span>/<span style="color: rgba(128, 0, 128, 1)">0.504</span> ms</pre>
</div>
<h1>电池健康</h1>
<p>目前还不清楚这是否在IOS中引起关注,但取决于UIDevice电池API是,您可以使用它们来识别设备的电池健康。(Olejnik,Acar,Castelluccia,&amp;Diaz,2016年)</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> timestampedBatteryLevels: [(Date, Float)] =<span style="color: rgba(0, 0, 0, 1)"> []

</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> UIDevice.current.isBatteryMonitoringEnabled {
timestampedBatteryLevels.append((Date(), UIDevice.current.batteryLevel))
}</span></pre>
</div>
<blockquote>
<p>因此,电池级API是在Firefox 55中删除.如果这看起来很奇怪,那么考虑一下苹果公司(Apple)最近发布了一项iOS的安全更新,因为研究人员证实,陀螺仪校准设置中的微小差异可以用来唯一地识别设备。(张,贝雷斯福,雪莱,2019年)</p>
</blockquote>
<p><strong>另外,如果你想一起进阶,不妨添加一下交流群,选择加入一起交流,一起学习。期待你的加入!(进群可领取学习礼包)</strong></p>
<h1>参考文献</h1>
<ul>
<li>&nbsp;de Montjoye,Y.-A.,Hidalgo,C.A.,Verleysen,M.,&amp;Blondel,V.D.(2013年)。在人群中独一无二:人类移动的隐私范围。科学报告, 3、1376号。https://doi.org/10.1038/srep01376</li>
<li>&nbsp;Sweeney,L.(2000年)。简单的人口统计往往能识别出独特的人。卡内基梅隆大学,数据隐私...工作文件。从http://dataprivacylab.org/projects/identifiability/检索</li>
<li>&nbsp;Weinberg,Z.,Cho,S.,Christin,N.,Sekar,V.,&amp;Gill,P.(2018)。如何捕捉代理说谎:验证网络代理的物理位置与主动地理定位。在……里面2018年因特网计量会议记录(第203-217页)。纽约,纽约,美国:ACM。https://doi.org/10.1145/3278532.3278551</li>
<li>&nbsp;Olejnik,L.,Acar,G.,Castelluccia,C.,&amp;Diaz,C.(2016)。漏水的电池。在……里面第十次数据隐私管理和安全保证国际讲习班的订正论文-第9481卷(第254至263页)。纽约,纽约,美国:斯普林格-维拉格纽约公司。https://doi.org/10.1007/978-3-319-29883-2_18</li>
<li>&nbsp;张,J.,贝雷斯福德,A.R.,&amp;Sheret,I.(2019)。SensorID:用于智能手机的传感器校准指纹。在……里面第40届IEEE安全与隐私专题讨论会会议纪要...IEEE。</li>
</ul>
<p>翻译地址:https://nshipster.com/device-identifiers/</p>

</div>
<div id="MySignature" role="contentinfo">
    既然已经在最黑暗的角落,那无论现在朝哪走,都是一一向着光亮,只要你肯!<br><br>
来源:https://www.cnblogs.com/21cm/p/11806355.html
頁: [1]
查看完整版本: iOS开发高级分享 - iOS上的设备标识符和指纹