关于为移动应用程序创建API:为移动应用程序创建API – 身份验证和授权

Creating an API for mobile applications - Authentication and Authorization

概述

我正在为我的应用程序创建一个(REST)API。最初/主要目的是供移动应用程序(iPhone、Android、Symbian等)使用。我一直在研究基于Web的API的身份验证和授权的不同机制(通过研究其他实现)。我已经把大部分基本概念都考虑进去了,但仍在一些领域寻求指导。我最不想做的就是重新设计方向盘,但是我没有找到任何符合我标准的标准解决方案(但是我的标准被误导了,所以请随意批评这一点)。此外,我希望所有使用API的平台/应用程序的API都是相同的。

小精灵

因为我知道这可能是提供的第一个解决方案,所以我会继续提出我对OAuth的异议。对于移动应用程序(或者更具体地说是非Web应用程序),让应用程序(转到Web浏览器)进行身份验证似乎是错误的。此外,浏览器无法(我知道)将回调返回到应用程序(尤其是跨平台)。我知道有几个应用程序可以做到这一点,但它只是感觉错误,并在应用UX中有所突破。

要求

  • 用户在应用程序中输入用户名/密码。
  • 每个API调用都由调用应用程序标识。
  • 开销保持在最低水平,授权方面对开发人员来说是直观的。
  • 该机制对最终用户(其登录凭据未公开)和开发人员(其应用程序凭据未公开)都是安全的。
  • 如果可能,不需要HTTPS(绝对不是硬要求)。
  • 我当前对实施的思考

    外部开发人员将请求一个API帐户。他们将收到一个apikey和apisert。每个请求至少需要三个参数。

    • ApiKey-在注册时提供给开发者
    • timestamp-双倍作为给定apikey的每个消息的唯一标识符
    • hash-时间戳的hash+apisecret

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

    对于经过身份验证的请求(代表用户完成的请求),在使用访问令牌路由或用户名和密码哈希组合之间,我还没有决定。无论哪种方式,在某个时候都需要用户名/密码组合。因此,当它执行此操作时,将使用由若干条信息(apikey、apisecret、timestamp)组成的哈希+密码。我很想得到这方面的反馈。仅供参考,他们必须先散列密码,因为我没有散列密码存储在我的系统中。

    结论

    仅供参考,这不是一个关于如何构建/构造API的请求,通常只是关于如何处理来自应用程序内部的身份验证和授权的请求。

    随机思考/奖励问题

    对于只需要一个apikey作为请求的一部分的API,如何防止apikey所有者以外的其他人看到apikey(从明文发送以来),并发出过多的请求来将其推到使用限制之外?也许我只是想过头了,但不应该有什么东西来验证请求是否已验证给了apikey所有者吗?在我的例子中,这就是apisecret的目的,它永远不会被显示/传输而不被散列。

    说到哈希斯,MD5和HMAC-SHA1怎么样?当所有值都使用足够长的数据(即apisert)进行哈希处理时,这真的很重要吗?

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


    在我的项目中,我对登录部分的思考方式是:

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

  • 要登录应用程序计算用户密码的散列值,然后使用login_token散列密码以获取值,然后返回login_token和组合散列值。

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

  • 这样做的好处是,您永远不会将用户的密码存储在服务器上,密码永远不会以明文形式传递,密码散列只在创建帐户时以明文形式传递(尽管可能有解决方法),而且在使用时,从数据库中删除login_token,应该可以安全地避免重播攻击。


    这是一个非常多的问题,我想相当多的人都没能读完。)

    我对Web服务身份验证的经验是,人们通常会对它进行过多的设计,而问题与您在网页上遇到的问题是相同的。可能非常简单的选项包括登录步骤的https,返回一个令牌,要求在将来的请求中包含它。您还可以使用HTTP基本身份验证,只需在头中传递内容。为了增加安全性,经常旋转/终止令牌,检查请求是否来自同一个IP块(这可能会变得混乱,尽管移动用户在单元之间移动),结合API密钥或类似的。或者,在对用户进行身份验证之前,执行OAuth的"请求密钥"步骤(有人已经在以前的答案中提出了这一点,这是一个好主意),并将其用作生成访问令牌所需的密钥。

    另一个我还没有使用过的替代品是xauth,但我听说它是一个对设备友好的替代品。看一看,如果你用的话,我真的很想听听你的印象是什么。

    对于散列来说,sha1更好一点,但不要被挂断——无论设备可以轻松(并且在性能方面很快)实现什么,都可能是好的。

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


    Twitter通过支持他们称为xauth的变体来解决OAuth中的外部应用程序问题。不幸的是,已经有太多的其他计划用这个名字,所以它可能会混淆排序。

    协议是OAuth,只是跳过了请求令牌阶段,并在收到用户名和密码后立即发出访问令牌对。(从这里的步骤e开始。)这个初始请求和响应必须是安全的-它以明文形式发送用户名和密码,并接收回访问令牌和秘密令牌。一旦配置了访问令牌对,对于会话的其余部分,初始令牌交换是通过OAuth模型还是通过XAuth模型与客户机和服务器无关。这有一个优势,即您可以利用现有的OAuth基础架构,并且对移动/Web/桌面应用程序的实现几乎相同。主要的缺点是,应用程序被授予访问客户端用户名和密码的权限,但您的需求似乎授权使用这种方法。

    无论如何,我想同意你和其他几个回答者的直觉:不要试图从头开始创造新的东西。安全协议可以很容易启动,但总是很难做好,而且它们越复杂,您的第三方开发人员就越不可能针对它们实现安全协议。您假设的协议与O(X)auth-api-key/api-secret、nonce、sha1散列非常相似,但开发人员不需要使用现有的许多库中的一个库,而是需要自己滚动。


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

    假设是这样的话,那么我会这样做(但我只不过是因为我是一个Java开发者,所以一个C的家伙会做不同的事情):

    RESTful身份验证和授权服务

  • 这只能通过https防止窃听。
  • 它将基于RestEasy、Spring Security和CA(用于跨多个应用程序的单一登录)的组合。
  • 它将与浏览器和启用Web的客户端应用程序一起工作
  • 将有一个基于Web的帐户管理界面,允许用户编辑其详细信息,并允许管理员(针对特定应用程序)更改授权级别。
  • 客户端安全库/应用程序

  • 对于每个支撑平台(例如Symbian、Android、iOS等)创建适当实施本机安全库平台语言(如Java语言)目标c、c等)
  • 图书馆应管理HTTPS请求使用可用的API形成对于给定平台(例如Java)使用URL连接等)
  • 一般认证和授权库全部)将编码到特定的接口,如果它任何变化都要确保灵活。遵循现有设计选择,如Spring Security。
  • 既然30000英尺的视野已经完成了,你该怎么做呢?嗯,基于服务器端列出的技术和浏览器客户端创建一个身份验证和授权系统并不难。与HTTPS结合,框架将提供一个基于由身份验证过程生成的共享令牌(通常表示为cookie)的安全过程,并在用户希望做什么时使用。每当发生任何请求时,客户端都会向服务器提供此令牌。

    在本地移动应用程序的情况下,您似乎正在寻找一个执行以下操作的解决方案:

  • 客户端应用程序有一个定义的访问控制列表(ACL),控制对方法调用的运行时访问。例如,给定的用户可以从一个方法中读取集合,但是他们的ACL只允许访问名为q的对象,因此安全拦截器可以安静地提取集合中的某些数据。在Java中,这很简单,您只需在调用代码上使用Spring安全注释,并实现一个合适的ACL响应过程。在其他语言中,您是独立的,可能需要提供调用到安全库的样板安全代码。如果该语言支持面向方面编程(AOP),那么在这种情况下应该充分地使用它。
  • 安全库将完整的授权列表缓存到当前应用程序的专用内存中,这样它就不必保持连接。根据登录会话的长度,这可能是一个永远不会重复的一次性操作。
  • 无论你做什么,不要试图发明你自己的安全协议,或者默默无闻地使用安全。您将永远无法为此编写比当前可用和免费的更好的算法。此外,人们信任众所周知的算法。因此,如果您说您的安全库使用SSL、HTTPS、SpringSecurity和AES加密令牌的组合为本地移动应用程序提供授权和身份验证,那么您将立即在市场上获得可信性。

    希望这对你有所帮助,祝你的事业好运。如果您想了解更多信息,请告诉我——我已经编写了很多基于Spring安全性、ACL等的Web应用程序。


    参加派对的时间太晚了,但我想再多加点,让对这个问题感兴趣的人考虑一下。我为一家从事移动API安全解决方案(Approv)的公司工作,因此这整个领域肯定与我的兴趣相关。

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

    在建议的解决方案中,您提到至少需要三个参数:

    • apikey-注册时提供给开发者
    • timestamp-双倍作为给定apikey的每个消息的唯一标识符
    • hash-时间戳的hash+apisecret

    这意味着对于某些API调用,不需要用户名/密码。这对于不想强制登录的应用程序(例如,在网上商店浏览)很有用。

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

    为了应对这种威胁,根据数据的价值,您可以做很多事情。模糊化是一种很简单的方法,使提取秘密变得更加困难。有一些工具可以为您做到这一点,对Android更是如此,但是您仍然需要有生成散列的代码,并且一个足够熟练的人总是可以直接调用执行散列的函数。

    另一种缓解不需要登录的API过度使用的方法是限制流量,并可能识别和阻止可疑的IP地址。您希望投入的精力在很大程度上取决于数据的价值。

    除此之外,你可以很容易地进入我日常工作的领域。不管怎样,这是保护API的另一个方面,我认为这一点很重要,并且希望能够标记出来。