NSDate:获取与设备时钟无关的精确时间?

时间:2012-08-31 19:38:07

标签: objective-c ios nsdate

  

可能重复:
  How can I locally detect iPhone clock advancement by a user between app runs?
  Is there a way to determine the actual time and date in iOS (not the time of the device)
  Is there a clock in iOS that can be used that cannot be changed by the user

我正在使用基于订阅的自动续订应用。当应用程序收到Apple的最新收据时,它会将expires_date_ms密钥存储在NSUserDefaults中。该日期过后30天,该应用程序会检查Apple以查看订阅是否仍处于活动状态。该应用可被视为离线应用,但必须每30天连接一次互联网才能检查订阅状态。此时间比较将用于告诉用户他/她必须连接。

问题

我使用下面的代码将当前时间与expires_date_ms

进行比较
NSTimeInterval expDateMS = [[productInfo objectForKey:@"expires_date_ms"] doubleValue];
NSTimeInterval currentDateMS = ([[NSDate date] timeIntervalSince1970] * 1000);

if (currentDateMS > expDateMS)
    subExpired = YES;

这很好并且效果很好,但据我所知,有一个漏洞可以被利用 - 如果用户将设备的时钟设置为一个小时/月/十年,则时间比较将变得不可靠,因为{{1} }使用设备的当前时间(如果我错了,请纠正我。)

问题

有没有办法检索与设备无关的时间(以毫秒为单位)?一个可以准确可靠地测量,而不考虑设备时钟?

4 个答案:

答案 0 :(得分:6)

您需要从可靠的官方时间服务器连接/检索信息,并在您的应用中使用该时间数据。例如,here's a world time server with an easy-to use API

答案 1 :(得分:6)

虽然Kevin和H2CO3完全正确,但还有其他解决方案用于检查订阅(我希望不需要毫秒精度......)

首先观看UIApplicationSignificantTimeChangeNotification,以便收到时间突然变化的通知。如果你被停职,这甚至会被送到你手中(虽然如果你被终止我不相信你会收到它)。当有载波时间更新时会调用它,并且当有手动时间更新(检查)时,我相信它被调用。它也会在当地午夜和DST更改时调用。关键是当时间突然改变时,它经​​常被调用。

跟踪进入后台的时间。跟踪回到前台的时间。如果时间从根本上向后移动(超过一天或两天),请建议您访问网络以检查事物。每当您使用服务器办理登机手续时,都应该告诉您它认为的时间。您可以使用它来同步系统。

您可以类似地跟踪您的实际运行时间。如果它与明显的运行时非常不同步,那么请再次请求访问网络以进行同步。

我确信攻击者可以在这个系统中潜行35天或者其他任何东西而不是30天,但是任何愿意努力工作的人都会破解你的软件并完全取出结账。这里的重点是未提交的攻击者只是搞乱他们的时钟。你可以很好地抓住它。

你应该仔细测试,并且非常犹豫地指责用户任何事情。只需连接到您的服务器就足以让合法用户再次工作。

答案 2 :(得分:4)

以下是我能想到的三个选项:

  1. clock_gettime(CLOCK_MONOTONIC) 获取当前系统的正常运行时间。这是相对不可靠的,因为如果用户重新启动,则重置。您可以保存最后使用的值,并在启动时使用上次保存的值作为偏移量,但问题是设备关闭的时间将不会被计算。

  2. mach_absolute_time() 计算自上次重启以来的CPU滴答数。它可以通过CACurrentMediaTime轻松获取。请注意,这可以通过重新启动设备来重置,因此如果更改时间非常重要,我不确定你是否会这样做。

  3. 网络时间协议(NTP)是一种用于同步计算机系统时钟的网络协议。实际上,所有NTP都在查询时间服务器。可以找到适用于NTP的iOS库here

  4. 所以前两种方法不需要连接,而第三种方法则需要连接。然而,第三种方法是唯一万无一失的方法。

答案 3 :(得分:2)

没有不可变的设备时钟在重新启动后持续存在。获得可信赖时间的唯一方法是联系您信任的远程服务器并询问其时间。