为移动应用程序创build一个API – 身份validation和授权

概观

我正在为我的应用程序创build一个(REST)API。 初始/主要目的是供移动应用程序(iPhone,Android,Symbian等)使用。 我一直在寻找不同的机制来validation和授权基于networking的API(通过学习其他实现)。 我的头脑里缠绕着大部分的基本概念,但仍然在一些领域寻找指导。 我想做的最后一件事是重新发明轮子,但是我没有find符合我的标准的标准解决scheme(但是我的标准被误导了,所以也可以随意批评)。 另外,我希望API对于所有使用它的平台/应用程序都是一样的。

OAuth的

我会继续向oAuth抛出我的反对意见,因为我知道这可能是提供的第一个解决scheme。 对于移动应用程序(或更具体的非Web应用程序),将应用程序(转到Web浏览器)进行身份validation似乎是错误的。 此外,浏览器无法(我知道)将callback函数返回给应用程序(特别是跨平台)。 我知道有几个应用程序可以这样做,但是它只是感觉不对而且在应用程序用户体验(UX)方面有所突破。

要求

  1. 用户input用户名/密码到应用程序。
  2. 每个API调用都由调用应用程序标识。
  3. 开销保持在最低限度,对于开发者来说,authentication方面是直观的。
  4. 该机制对于最终用户(他们的login凭证不公开)以及开发者(他们的应用凭证不公开)是安全的。
  5. 如果可能的话,不要求https(绝不是硬性要求)。

我现在的执行思路

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

  • apikey – 在注册时给予开发者
  • 时间戳 – 双倍作为给定apikey的每个消息的唯一标识符
  • 散列 – 时间戳+ apisecret的散列

apikey需要识别发出请求的应用程序。 时间戳的作用类似于oauth_nonce,并避免/减轻重放攻击。 哈希确保请求实际上是从给定apikey的所有者发出的。

对于通过身份validation的请求(代表用户完成的),我仍然不确定要使用access_token路由还是用户名和密码哈希组合。 无论哪种方式,在某个时候,用户名/密码组合将是必需的。 所以当它的时候,会使用几条信息(apikey,apisecret,timestamp)和密码的散列。 我喜欢这方面的反馈意见。 仅供参考,他们将不得不先散列密码,因为我不存储密码在我的系统没有散列。

结论

仅供参考,这不是一个如何构build/构buildAPI的请求,而只是如何处理来自应用程序中的validation和授权。

随机思考/奖金问题

对于仅需要apikey作为请求一部分的API,如何防止除apikey所有者以外的人能够看到apikey(由于发送明文),并提出过多的请求来推动他们超出使用限制? 也许我只是在想这个,但是不应该有什么东西来validation一个请求被apikey所有者validation了吗? 在我的情况下,这是apisecret的目的,它不会被显示/传输没有被哈希。

说到哈希,md5 vs hmac-sha1呢? 当所有的数据都用足够长的数据(即apisecret)进行散列时,真的很重要吗?

我以前曾经考虑添加每个用户/行盐到我的用户密码哈希。 如果我这样做,那么应用程序如何能够在不知道所使用的盐的情况下创build一个匹配的哈希?

我想在我的项目中做这个login部分的方式是:

  1. 在login之前,用户从服务器请求login_token 。 这些是根据请求生成并存储在服务器上的,并且可能具有有限的生命周期。

  2. login应用程序计算用户密码的散列,然后用login_token散列密码以获取值,然后返回login_token和组合散列。

  3. 服务器检查login_token是否已经生成,将其从有效的login_token列表中login_token 。 然后,服务器将其存储的用户密码散列与login_token并确保它与提交的组合令牌相匹配。 如果匹配,您已经validation了您的用户。

这样做的好处是,你永远不会在服务器上存储用户的密码,密码永远不会被传入,密码哈希值只能通过明确的帐户创build来传递(尽pipe可能会有解决办法),它应该是安全的重放攻击,因为login_token从使用的数据库中删除。

这是一个很多的问题,我想很多人没有设法一直读到底:)

我对Web服务身份validation的经验是,人们通常会对其进行过滤,问题只会在网页上遇到。 可能非常简单的选项包括用于login步骤的https,返回一个令牌,要求将其包含在未来的请求中。 你也可以使用http基本authentication,只是在头部传递的东西。 为了增加安全性,经常旋转/过期令牌,检查请求来自同一个IP块(当移动用户在单元之间移动时,这可能会变得麻烦),与API密钥或类似组合。 或者,在对用户进行身份validation之前,执行oauth的“请求密钥”步骤(有人在之前的回答中已经提出了这个build议,这是一个好主意),并将其用作生成访问令牌所需的密钥。

另一个我还没有用过的方法,但是我听说过很多关于oAuth的设备友好的替代方法,就是xAuth 。 看看它,如果你使用它,那么我真的很感兴趣,听听你的印象是什么。

对于散列,sha1稍微好一点,但是不要挂上电话 – 无论设备如何轻松地(快速地在性能意义上)实现可能都是好的。

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

那么你所追求的是一种服务器端authentication机制,它将处理移动应用程序的authentication和授权方面?

假设是这样的话,那么我会按如下方式处理它(但是,只有因为我是一个Java开发人员,所以C#人会做不同的):

RESTfulauthentication和授权服务

  1. 这只会通过HTTPS来防止窃听。
  2. 它将基于RESTEasy , Spring Security和CAS (用于跨多个应用程序的单点login)的组合。
  3. 它将与浏览器和支持Web的客户端应用程序一起工作
  4. 将会有一个基于networking的帐户pipe理界面,允许用户编辑他们的详细信息,pipe理员(特定应用程序)可以更改授权级别

客户端安全库/应用程序

  1. 对于每个支持的平台(例如Symbian,Android,iOS等),以平台本地语言(例如Java,ObjectiveC,C等)创build安全库的合适实现。
  2. 该库应该使用给定平台的可用API来pipe理HTTPS请求的形成(例如Java使用URLConnection等)
  3. 一般authentication和授权库('COS就是这样)的消费者将编码到一个特定的接口,如果它发生变化将不会高兴,所以确保它非常灵活。 遵循现有的deviseselect,例如Spring Security。

所以现在从3万英尺的观点是完整的你怎么去做呢? 那么,在浏览器客户端的基础上创build一个基于服务器端上市技术的authentication和授权系统并不难。 与HTTPS相结合,框架将提供一个基于共享令牌(通常以cookie的forms)由authentication过程生成的安全stream程,并在用户希望做某事时使用。 每当发生任何请求时,该令牌都由客户端提供给服务器。

在本地移动应用程序的情况下,似乎您正在执行以下操作的解决scheme:

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

不pipe你做什么, 都不要试图发明自己的安全协议 ,或者使用默默无闻的安全措施。 你永远无法为这个写一个更好的algorithm。 另外,人们相信众所周知的algorithm。 因此,如果您说安全库为本地移动应用程序使用SSL,HTTPS,SpringSecurity和AESencryption令牌的组合提供授权和身份validation,那么您将立即在市场上获得信任。

希望这会有所帮助,祝你好运。 如果您想了解更多信息,请告诉我 – 我已经编写了很多基于Spring Security,ACL等的Web应用程序。

Twitter通过支持一个称为xAuth的变体来解决oAuth中的外部应用程序问题。 不幸的是,已经有很多这个名字的其他计划,所以可以混淆整理。

该协议 oAuth,除了它跳过请求令牌阶段,并立即发出一个访问令牌对收到用户名和密码。 (从这里的步骤E开始 。)这个初始请求和响应必须是安全的 – 它以明文forms发送用户名和密码并接收访问令牌和秘密令牌。 一旦configuration了访问令牌对,最初的令牌交换是通过oAuth模型还是xAuth模型与客户端和服务器在会话的其余部分都不相关。 这样做的好处是您可以利用现有的oAuth基础架构,并且具有与移动/ Web /桌面应用程序几乎相同的实现。 主要的缺点是应用程序被授予访问客户端的用户名和密码,但看起来像你的要求强制这种方法。

无论如何,我想同意你的直觉和其他几个回答者的直觉:不要试图从头开始构build新的东西。 安全协议可以很容易地开始,但总是很难做到,而且越复杂,它们就越不可能让你的第三方开发者能够对付它们。 您的假设协议与o(x)Auth – api_key / api_secret,nonce,sha1哈希非常类似 – 但是您不需要使用现有的许多库中的一个,您的开发人员就需要自行开发。

超级迟到的晚会,但我想在这个问题上感兴趣的任何人考虑一些额外的观点。 我为一家做移动API安全解决scheme( approov )的公司工作,所以这整个领域肯定与我的兴趣相关。

首先,尝试保护移动API时要考虑的最重要的事情是多less值得你 。 对于银行来说,正确的解决scheme不同于正在为乐趣而做事的人的正确解决scheme。

在提出的解决scheme中,您提到至less需要三个参数:

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

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

这与用户authentication的问题稍有不同,更像是软件的authentication或authentication。 没有用户,但您仍然希望确保没有对您的API的恶意访问。 因此,您使用您的API密码来签署stream量并将访问该API的代码标识为真实的。 这个解决scheme的潜在问题是,你必须泄露每个版本的应用程序内的秘密。 如果有人能够提取这个秘密,他们可以使用你的API,模仿你的软件,但是做他们喜欢的任何事情。

为了应对这种威胁,根据数据的价值,你可以做很多事情。 混淆是一个简单的方法,使得难以提取秘密。 有些工具会为你做,对于Android来说更是如此,但是你仍然必须有能够生成你的哈希的代码,而且有足够技能的人可以直接调用直接进行哈希的函数。

另一种减less过度使用不需要login的API的方法是限制stream量,并可能识别和阻止可疑IP地址。 你想要付出多less努力将主要取决于你的数据是多么有价值。

除此之外,您可以轻松开始进入我日常工作的领域。 无论如何,这是API的另一个方面,我认为是重要的,并希望标志。