【问题标题】:Verifying a user when backing up data to a server将数据备份到服务器时验证用户
【发布时间】:2012-01-02 19:52:35
【问题描述】:

注意:尽管我在 iOS 应用程序的上下文中提出了这个问题,但我认为它并不局限于在该特定操作系统上运行的应用程序。

我正在开发一个将用户数据备份到服务器的 iOS 应用程序,并且我正在尝试找出在服务器端验证被更新的用户实际上是真实用户的最佳方法。每个用户都有一个 id (uid)。如果这就是我依赖服务器端的全部,那么我想这个过程会是这样的:

  • 用户第一次运行应用程序
  • 在应用程序中创建帐户,该应用程序与服务器通信以在服务器上创建帐户并获取唯一的“用户 ID”(uid)
  • 应用存储此 uid,以便在与服务器的后续通信中识别用户

但是,如果有人要破解他们 iPhone 上的应用程序,他们可以更改用户 ID 值,然后他们会立即访问/允许他们修改其他用户的数据。

我正在考虑的当前解决方案是用户接收 2 个唯一 ID、uid(只是一个自动递增的数字)和一个更长、更复杂的密钥字符串。因此,与服务器的所有通信都必须同时发送 uid 和密钥。服务器将验证它们是否匹配,以确保用户确实是应用程序所说的那个人。

所以,我的问题有两个:

  1. 这是实现此目的的正确方法吗?还是我应该采用其他一些标准方法?
  2. 如果这是正确的方法,生成唯一密钥的推荐方法是什么?

【问题讨论】:

标签: ios security verification server-side-validation


【解决方案1】:

首先,如果您愿意,您可以使用更复杂的值作为用户 ID(例如 UUID)。随着服务的扩展,单调递增的 ID 变得难以管理。

当安全网站在浏览器上留下安全 cookie 以记住会话时,您会遇到同样的问题。这些 cookie 确实包含用户 ID,但必须防止篡改。这通常是通过在服务器上对 cookie 进行签名,然后再将其发回。

所以你要做的是:

  1. 在服务器上生成用户 ID,并使用它来创建某种“身份验证令牌”以供客户端登录。
  2. 使用只有您的服务器知道的密钥签署服务器上的身份验证令牌。
  3. 将身份验证令牌发送到客户端,并在其中存储它以供所有后续登录使用。通过 HTTPS 传输身份验证令牌,以防止其他人在网络上窥探它。

当应用程序登录时,将身份验证令牌发送到服务器。如果被黑了,签名验证会失败,你会知道拒绝客户端。

考虑在签名令牌中也包含时间戳,这样它会在一段时间后过期,从而强制服务器定期重新生成身份验证令牌,这样可以在您的密钥被泄露时保护您。除非用户自己有一个共享的秘密/密码,否则他很难完全做到这一点,他也可以使用它来定期进行身份验证。取决于你需要走多远。

其他注意事项:如果您对某个用户的了解仅是他们生成的 UID,那么您无法让该用户稍后从其他 iOS 设备返回并在那里恢复他们的帐户,对吗?一般来说,如果用户将在他们的帐户中创建他们以后想要访问的任何“有价值”的东西,您可能希望创建一个更传统的用户帐户,并以电子邮件地址和密码等为后盾,这样他们就可以重新安装您的应用程序后再次访问该帐户。 (这可能与您的情况相关,也可能不相关。)

【讨论】:

  • 感谢您的回复。您列出的“其他注意事项”与我正在做的事情绝对相关。我假设我管理它的方式是:1)用户在一台 iOS 设备上登录,生成身份验证令牌并将其发送回设备。 2) 用户在不同的 iOS 设备上登录,服务器检查身份验证令牌是否已经存在并将其发回而不是创建一个新的。对吗?
  • 另外,您对 cookie 签名的描述听起来与我所说的服务器将生成的“更复杂的密钥字符串”相似。这是对的,还是我缺少真正区分两者的东西?最后,为了清楚起见,您建议按以下方式构造“身份验证令牌”:用户 ID + 时间戳,然后创建它的哈希?
  • @maxedison:您不需要检查现有的身份验证令牌;身份验证令牌只是您在必要时生成并发送给要求它的客户的东西。它成为关于您是否允许一个用户同时进行多个会话等的政策决定。
  • @maxedison:不,签名是特定的操作。您永远不会发送实际的密钥本身。密钥是秘密的,只存在于服务器上(不需要每个用户)。您连接您关心的数据(例如,用户 ID + 时间戳),然后对其进行哈希处理,并使用密钥对哈希进行签名。例如。 SHA1-HMAC 或 MD5-HMAC。这个想法是没有攻击者知道密钥,所以没有攻击者可以编造一个有效的签名哈希,只有你可以。因此,当它在您的服务器上验证时,您可以信任它。有意义吗?
  • @maxedison (根据您希望它的安全程度,您还可以使用“nonce”(附加到末尾的随机数,也与身份验证令牌一起发送)“加盐”连接数据和哈希的一部分)使密钥更难逆向工程。这对于你关心的东西来说可能太先进了。)
【解决方案2】:

我建议采用“标准网络浏览器方式”,让用户设置电子邮件(登录名)和密码。

当 iOS 设备连接到服务器(使用 HTTPS)时,它使用常规的“基本身份验证”登录,并收到一个在设定的时间段内有效的 cookie。只要设备在 cookie 的生命周期内不断向服务器请求数据,cookie 就会被更新,当 cookie 过期时,服务器会自动挑战客户端再次使用其存储的信息登录。

这有一些好处;

  • 用户可以通过定期重置密码的新设备重新登录他的帐户。简单直接地解决了问题。

  • 服务器端没有特殊的解决方案,任何服务器端脚本都可以像浏览器一样需要身份验证 - 内置功能。

  • 您不必发明自己的安全方案。每天有数百万浏览器使用此方案对网站进行身份验证。

  • 不绑定特定手机,如果用户有多个iOS设备,只需登录即可使用所有设备的同一个帐户。无需特殊设置程序。

换句话说;无需为您开发专门的解决方案,一般解决了如何处理登录信息、经过验证的安全性和易用性的问题。

在我看来,你真的无法击败它 :)

【讨论】:

  • 感谢您的回复,但我认为这正是@quixoto 所推荐的。
  • 其实差别还是蛮大的,我就不做点数了。让我鼓励您不要将数据存储在 cookie 中,或者尝试发明自己的签名方案,以便通过常规服务器端会话更好地解决问题。以 PHP 为例,当您登录时,它会生成一个随机 cookie,该 cookie 存储为地图服务器端的密钥,您可以在其中放置数据,然后发送到客户端。不发送敏感数据,当客户端发回随机cookie时,服务器只是在地图中查找并获取相关数据。将数据放入 cookie 不是一件好事。
  • 好的,我明白你在说什么。
猜你喜欢
  • 1970-01-01
  • 2021-04-27
  • 1970-01-01
  • 2016-05-16
  • 1970-01-01
  • 2016-07-30
  • 2017-08-15
  • 1970-01-01
  • 2012-08-28
相关资源
最近更新 更多