为移动应用程序创建 API-认证和授权

概述

我希望为我的应用程序创建一个(REST) API。最初/主要用途是供移动应用程序(iPhone、 Android、 Symbian 等)使用。我一直在研究基于 Web 的 API 的认证和授权的不同机制(通过研究其他实现)。我已经理解了大部分基本概念,但仍然在一些领域寻求指导。我想做的最后一件事是重新发明轮子,但我没有找到任何符合我的标准的标准解决方案(然而我的标准被误导了,所以也可以随意批评它)。此外,我希望所有使用它的平台/应用程序的 API 都是相同的。

奥特

我将继续并抛弃我对 oAuth 的反对意见,因为我知道这可能是第一个提供的解决方案。对于移动应用程序(或者更具体地说是非 Web 应用程序)来说,离开应用程序(到 Web 浏览器)进行身份验证似乎是错误的。此外,浏览器没有办法(我知道)将回调返回给应用程序(特别是跨平台)。我知道有几个应用程序可以做到这一点,但它只是感觉不对,让应用程序用户体验中断。

规定

  1. 用户在应用程序中输入用户名/密码。
  2. 每个 API 调用都由调用应用程序标识。
  3. 开销保持在最低限度,而且对于开发人员来说,认证方面是直观的。
  4. 该机制对于最终用户(不公开其登录凭据)和开发人员(不公开其应用程序凭据)都是安全的。
  5. 如果可能的话,不需要 https (绝不是硬性要求)。

当前实施工作的思考

外部开发人员将请求 API 帐户。他们将会收到一把钥匙和一个秘密钥匙。每个请求至少需要三个参数。

  • 注册时发给发展商
  • 时间戳-对于给定的 apikey,每条消息的唯一标识符加倍
  • Hash-时间戳的 hash + apissecret

需要 apikey 来标识发出请求的应用程序。时间戳的作用类似于 oauth _ nonce,可以避免/减轻重播攻击。散列确保请求实际上是从给定 apikey 的所有者发出的。

对于经过身份验证的请求(代表用户完成的请求) ,我还没有决定是使用 access _ token 路由,还是使用用户名和密码散列组合。无论哪种方式,在某些时候都需要用户名/密码组合。因此,当它这样做,一个散列的几个信息片段(apikey,apissecret,时间戳) + 密码将被使用。仅供参考,他们必须首先哈希密码,因为我不存储密码在我的系统中没有哈希。

结论

仅供参考,这不是一个关于如何构建/结构化 API 的请求,而是关于如何仅在应用程序内部处理身份验证和授权的请求。

随机的想法/奖励问题

对于只需要 apikey 作为请求的一部分的 API,如何防止 apikey 所有者以外的其他人能够看到 apikey (自从明确发送以来)并提出过多的请求来超过使用限制?也许我只是想多了,但是难道不应该有一些东西来验证某个请求是否已经被 apikey 的所有者验证了吗?在我的案例中,这就是这个秘密的目的,它从来没有显示/传输没有被散列。

说到散列,md5和 hmac-sha1怎么样?当所有的值都使用足够长的数据进行散列时(即。阿皮斯克雷特) ?

我之前一直在考虑向我的用户密码散列中添加每个用户/行的 salt。如果要这样做,应用程序如何能够在不知道使用的 salt 的情况下创建匹配散列?

62498 次浏览

我考虑在我的项目中进行登录的方式是:

  1. 在登录之前,用户从服务器请求 login_token。它们是根据请求生成并存储在服务器上的,并且可能具有有限的生存期。

  2. 登录应用程序计算用户密码的哈希值,然后用 login_token对密码进行哈希处理得到一个值,然后返回 login_token和组合哈希值。

  3. 服务器检查它生成的 login_token,并将其从有效的 login_token列表中删除。然后,服务器将其存储的用户密码哈希值与 login_token组合起来,并确保它与提交的组合令牌相匹配。如果它匹配您已经验证了您的用户。

这样做的好处是,你永远不会在服务器上存储用户的密码,密码从来不会在 clear 中传递,密码哈希只有在创建账户时才会在 clear 中传递(尽管可能有其他方法可以绕过这一点) ,而且当使用数据库时从数据库中删除 login_token时,它应该是安全的,不会受到重播攻击。

因此,您所追求的是某种服务器端身份验证机制,它将处理移动应用程序的身份验证和授权方面的问题?

假设情况是这样的,那么我会按照下面的方法来处理它(但仅仅是因为我是一个 Java 开发人员,所以 C # 人员的做法会有所不同) :

RESTful 身份验证和授权服务

  1. 这只能在 HTTPS 上工作,以防止窃听。
  2. 它将基于 放松春天保安公司民安队的组合(用于跨多个应用程序的单点登录)。
  3. 它将同时适用于浏览器和支持 Web 的客户端应用程序
  4. 将有一个基于网络的帐户管理界面,允许用户编辑他们的详细信息,管理员(对于特定的应用程序)改变授权级别

客户端安全库/应用程序

  1. 对于每个受支持的平台(例如。 Symbian,Android,iOS 等)创建一个 实施 本机中的安全库 平台的语言(例如, 目标 C、 C 等)
  2. 图书馆 应该管理 HTTPS 请求 使用可用的原料药组成 对于给定的平台(例如 Java 使用网址连接等)
  3. 消费者的一般认证和 认可图书馆(因为那是 所有它是)将代码到一个特定的 接口,并不会高兴,如果它 所以要确保它非常 灵活。遵循现有的设计 像 Spring Security 这样的选择。

那么,现在从30,000英尺的视野是完整的,你如何着手去做呢?基于浏览器客户端服务器端列出的技术,创建一个身份验证和授权系统并不难。与 HTTPS 相结合,这些框架将提供一个基于认证过程生成的共享令牌(通常表示为 cookie)的安全进程,并在用户希望执行某些操作时使用该进程。无论何时发生任何请求,客户机都会将此令牌呈现给服务器。

在本地移动应用程序的案例中,似乎你在寻找一个解决方案,它可以做到以下几点:

  1. 客户端应用程序具有已定义的访问控制列表(ACL) ,该列表控制对方法调用的运行时访问。例如,给定用户可以从方法中读取集合,但是他们的 ACL 只允许访问名称中带有 Q 的对象,因此集合中的一些数据由安全拦截器安全地提取。在 Java 中,这很简单,只需在调用代码上使用 Spring Security 注释并实现一个合适的 ACL 响应过程。在其他语言中,您可能需要自己提供调用到安全库中的样板安全代码。如果语言支持 AOP (面向方面编程) ,那么在这种情况下应该充分利用它。
  2. 安全库将完整的授权列表缓存到当前应用程序的私有内存中,这样它就不必保持连接。根据登录会话的长度,这可能是一次性操作,永远不会重复。

无论你做什么,不要试图发明你自己的安全协议,或使用隐藏式安全。对于这个问题,你永远不可能写出比目前可用和免费的算法更好的算法。此外,人们信任著名的算法。因此,如果您说您的安全库使用 SSL、 HTTPS、 SpringSecurity 和 AES 加密令牌为本地移动应用程序提供授权和认证,那么您将立即在市场上获得信誉。

希望这能帮到你,祝你创业好运。如果你想要更多的信息,让我知道-我已经写了相当多的网络应用程序的基础上,春天安全,ACL 等。

这是一大堆问题中的一个,我猜有不少人没能读到最后:)

我在 Web 服务身份验证方面的经验是,人们通常会对它进行过度设计,而问题与您在 Web 页面上遇到的问题完全相同。可能的非常简单的选项包括登录步骤的 https、返回令牌、要求将其包含在以后的请求中。您还可以使用 http 基本身份验证,并只在头部传递内容。为了增加安全性,经常轮换/过期令牌,检查请求是否来自同一个 IP 块(当移动用户在单元格之间移动时,这可能会变得混乱) ,结合 API 密钥或类似的。或者,在验证用户之前执行 oauth 的“ request key”步骤(已经有人在前一个答案中提出了这个建议,这是一个好主意) ,并将其作为必需的密钥来生成访问令牌。

我还没有使用过的一种替代方法是 XAuth,但是我听说过很多关于它作为一种设备友好的替代方法来替代 oAuth 的说法。看看它,如果你使用它,然后我真的很有兴趣听到你的印象是什么。

对于哈希,sha1稍微好一点,但是不要纠结于它——任何设备可以轻松(并且在性能意义上快速)实现的东西可能都不错。

希望能有所帮助,祝你好运:)

Twitter 通过支持一个称为 XAuth的变体解决了 oAuth 中的外部应用程序问题。不幸的是,已经有过多的其他方案使用这个名称,因此可能会令人困惑的排序。

协议 oAuth 跳过了请求令牌阶段,只是在收到用户名和密码后立即发出一个访问令牌对。(由 这里是 E 步开始)这个 首字母缩写请求和响应 必须保证安全-它以明文形式发送用户名和密码,并接收回访问令牌和秘密令牌。一旦配置了访问令牌对,无论初始令牌交换是通过 oAuth 模型还是 xAuth 模型,对于会话的其余部分,客户机和服务器都是无关的。这样做的好处是,您可以利用现有的 oAuth 基础设施,并且对于移动/web/桌面应用程序具有几乎相同的实现。主要的缺点是应用程序被授予访问客户机的用户名和密码的权限,但似乎您的需求强制使用这种方法。

无论如何,我同意你的直觉,也同意其他几个答案的直觉: 不要试图从头开始建立新的东西。安全协议可以很容易启动,但总是很难做好,而且它们越复杂,第三方开发人员就越不可能针对它们实现。你假设的协议非常类似于 o (x) Auth-api _ key/api _ secret,nonce,sha1散列-但是你的开发人员不能使用现有的库中的一个,而是需要自己建立库。

虽然已经很晚了,但是我还是想为那些对这个问题感兴趣的人提供一些额外的建议。我在一家做移动 API 安全解决方案(批准)的公司工作,所以这整个领域绝对与我的兴趣相关。

首先,在尝试保护移动 API 时要考虑的最重要的事情是 它对你来说值多少钱。对于银行来说,正确的解决方案与对于某些人只是为了好玩而做事情的正确解决方案是不同的。

在拟议的解决办法中,你提到至少需要三个参数:

  • 在注册时发给开发人员
  • 时间戳-对于给定的 apikey,每条消息的唯一标识符加倍
  • Hash-时间戳的 hash + apissecret

这意味着,对于某些 API 调用,不需要用户名/密码。这对于您不希望强制登录的应用程序(例如,在线商店中浏览)非常有用。

这个问题与用户身份验证的问题稍有不同,更像是软件的身份验证或认证。没有用户,但是您仍然希望确保没有恶意访问您的 API。因此,您使用您的 API 秘密来签署流量,并确定访问 API 的代码是真正的。这个解决方案的潜在问题是,你必须在每个版本的应用程序中泄露秘密。如果有人可以提取秘密,他们可以使用你的 API,模仿你的软件,但做他们喜欢的任何事情。

为了应对这种威胁,你可以做很多事情,这取决于数据的价值。混淆视听是一种简单的方法,使得提取秘密变得更加困难。有一些工具可以为你做到这一点,对于 Android 来说更是如此,但是你仍然需要编写代码来生成你的散列,一个足够熟练的人总是可以直接调用进行散列的函数。

另一种防止过度使用不需要登录的 API 的方法是 油门流量,并可能识别和阻止可疑的 IP 地址。您希望付出的努力在很大程度上取决于您的数据的价值。

除此之外,你可以很容易地开始进入我日常工作的领域。无论如何,这是保护 API 的另一个方面,我认为这很重要,并且想要标记出来。