首页 文章

为移动应用程序创建API - 身份验证和授权

提问于
浏览
184

概述

我正在寻找为我的应用程序创建(REST)API . 初始/主要目的是供移动应用程序(iPhone,Android,Symbian等)使用 . 我一直在研究基于Web的API的身份验证和授权的不同机制(通过研究其他实现) . 我已经把头脑包裹在大多数基本概念中,但仍然在一些领域寻找指导 . 我想要做的最后一件事就是重新发明轮子,但我找不到任何符合我标准的标准解决方案(不过我的标准是误导的,所以也可以随意批评) . 此外,我希望API对于使用它的所有平台/应用程序都是相同的 .

oAuth

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

要求

  • 用户在应用程序中输入用户名/密码 .

  • 每个API调用都由调用应用程序标识 .

  • 开销保持在最低限度,auth方面对开发人员来说非常直观 .

  • 该机制对于最终用户(他们的登录凭证未公开)以及开发人员(他们的应用程序凭证未公开)都是安全的 .

  • 如果可能,不要求https(绝不是硬性要求) .

我目前对实施的看法

外部开发人员将请求API帐户 . 他们将获得一个apikey和apisecret . 每个请求至少需要三个参数 .

  • apikey - 在注册时交给开发人员

  • timestamp - 兼作给定apikey的每条消息的唯一标识符

  • hash - apisecret时间戳的哈希值

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

对于经过身份验证的请求(代表用户完成的请求),我仍然未决定使用access_token路由或用户名和密码哈希组合 . 无论哪种方式,在某些时候都需要用户名/密码组合 . 因此,当它发生时,将使用密码的几个信息(apikey,apisecret,timestamp) . I'd love feedback on this aspect. 仅供参考,他们必须首先对密码进行哈希处理,因为我没有在没有散列的情况下将密码存储在我的系统中 .

结论

仅供参考,这不是要求如何构建/构建API,一般只是如何仅在应用程序内处理身份验证和授权 .

随机思考/奖金问题

对于仅需要apikey作为请求的一部分的API,如何防止apikey所有者以外的其他人看到apikey(因为明确发送)并提出过多请求以超过使用限制?也许我只是在想这个,但是不应该有什么东西可以验证请求是否已经被apikey所有者验证了?在我的情况下,这是apisecret的目的,它永远不会被显示/传输而不被哈希 .

说到哈希,md5和hmac-sha1怎么样?使用足够长的数据(即apisecret)对所有值进行散列时,真的很重要吗?

我之前一直在考虑为用户密码哈希添加每用户/行盐 . 如果我这样做,应用程序如何能够在不知道使用盐的情况下创建匹配的哈希?

5 回答

  • 9

    我正在考虑在我的项目中执行此登录部分的方式是:

    登录前

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

    • 登录应用程序计算用户密码的哈希值,然后用 login_token 哈希密码得到一个值,然后返回 login_token 和组合哈希值 .

    • 服务器检查 login_token 是否已生成,将其从有效 login_token 列表中删除 . 然后,服务器将其存储的用户密码哈希值与 login_token 组合,并确保它与提交的组合令牌匹配 . 如果匹配,则表示您已对用户进行身份验证 .

    这样做的好处是你永远不会在服务器上存储用户的密码,密码永远不会以明文形式传递,密码哈希只会在明确的帐户创建中传递(虽然可能有办法解决这个问题),它应该是安全的重播攻击,因为 login_token 在使用中从DB中删除 .

  • 4

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

    我对Web服务身份验证的体验是,人们通常会过度使用它,而且问题只与您在网页上遇到的问题相同 . 可能非常简单的选项包括登录步骤的https,返回令牌,要求将其包含在将来的请求中 . 您还可以使用http基本身份验证,只需传递 Headers 中的内容即可 . 为了增加安全性,请经常旋转/过期令牌,检查请求是否来自同一个IP块(这可能会因为移动用户在小区之间移动而变得混乱),与API密钥或类似组合 . 或者,在对用户进行身份验证之前,执行oauth的“请求密钥”步骤(有人在之前的回答中建议这一点并且这是一个好主意),并将其用作生成访问令牌的必需密钥 .

    作为oAuth的设备友好替代方案,我已经听过很多关于o6uth的替代方案是xAuth . 看看它,如果你使用它,那么我真的很想知道你的印象是什么 .

    对于散列,sha1稍微好一些,但不要挂断它 - 无论设备能够轻松(并且在性能意义上很快),实现都可能没问题 .

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

  • 8

    Twitter通过支持他们称之为xAuth的变体来解决oAuth中的外部应用程序问题 . 不幸的是,已经有很多其他具有此名称的方案,因此可能会让人感到困惑 .

    该协议是oAuth,除了它跳过请求令牌阶段并且在收到用户名和密码后立即发出访问令牌对 . (从step E here开始 . )这个初始请求和响应 must be secured - 它是's sending the username and password in plaintext and receiving back the access token and secret token. Once the access token pair has been configured, whether the initial token exchange was via the oAuth model or the xAuth model is irrelevant to both the client and server for the rest of the session. This has the advantage that you can leverage existing oAuth infrastructure and have very nearly the same implementation for mobile/web/desktop applications. The main disadvantage is that the application is granted access to the client'的用户名和密码,但看起来你的要求强制要求这种方法 .

    在任何情况下,我都同意你的直觉以及其他几位回答者的直觉:不要试图从头开始构建新东西 . 安全协议可以很容易地启动,但总是很难做到,并且它们变得越复杂,第三方开发人员就越不可能实现它们 . 你的假设协议非常类似于o(x)Auth - api_key / api_secret,nonce,sha1哈希 - 但是你不需要使用你的开发人员需要自己创建的许多现有库中的一个 .

  • 12

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

    假设是这种情况,那么我会按如下方式处理它(但只是'因为我是Java开发人员所以C#的人会以不同的方式做到这一点):

    The RESTful authentication and authorisation service

    • 这仅适用于HTTPS以防止窃听 .

    • 它将基于RESTEasySpring SecurityCAS的组合(用于跨多个应用程序的单点登录) .

    • 它适用于浏览器和支持Web的客户端应用程序

    • 将有一个基于Web的帐户管理界面,允许用户编辑他们的详细信息,以及管理员(针对特定应用程序)更改授权级别

    The client side security library/application

    • 对于每个支持的平台(例如Symbian,Android,iOS等),以平台的本机语言(例如Java,ObjectiveC,C等)创建合适的安全库实现

    • 库应该使用给定平台的可用API来管理HTTPS请求的形成(例如,Java使用URLConnection等)

    • 一般身份验证和授权库的消费者('cos that'就是它)将代码到特定的接口并且非常灵活地赢得了't be happy if it ever changes so make sure it' . 遵循现有的设计选择,例如Spring Security .

    那么现在30,000英尺的视图是完整的,你怎么去做呢?嗯,使用浏览器客户端在服务器端基于列出的技术创建身份验证和授权系统并不困难 . 结合HTTPS,框架将基于由身份验证过程生成的共享令牌(通常以cookie形式呈现)提供安全流程,并在用户希望执行某些操作时使用 . 无论何时发生任何请求,客户端都会将此令牌呈现给服务器 .

    对于本地移动应用程序,您似乎正在执行以下操作的解决方案:

    • 客户端应用程序具有定义的访问控制列表(ACL),用于控制对方法调用的运行时访问 . 例如,给定用户可以从方法中读取集合,但是他们的ACL仅允许访问其名称中具有Q的对象,因此集合中的某些数据被安全拦截器拉动 . 在Java中,这很简单,您只需对调用代码使用Spring Security注释并实现合适的ACL响应过程 . 在其他语言中,您可能需要自己动手提供调用安全库的样板安全代码 . 如果该语言支持AOP(面向方面编程),那么在这种情况下可以充分利用它 .

    • 安全库将完整的授权列表缓存到其中_632881必须保持连接 . 根据登录会话的长度,这可能是一次性操作,永远不会重复 .

    无论你做什么, don't try to invent your own security protocol ,或默默无闻地使用安全 . 你'll never be able to write a better algorithm for this than those that are currently available and free. Also, people trust well known algorithms. So if you say that your security library provides authorisation and authentication for local mobile applications using a combination of SSL, HTTPS, SpringSecurity and AES encrypted tokens then you'立即在市场上有信誉 .

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

  • 42

    超级晚会,但我想为任何对此问题感兴趣的人提出一些额外的要点 . 我为一家从事移动API安全解决方案的公司工作(approov),所以整个领域与我的兴趣无关 .

    首先,尝试保护移动API时要考虑的最重要事项是 how much it is worth to you . 银行的正确解决方案与正确处理好事的人的正确解决方案不同 .

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

    • apikey - 在注册时交给开发人员

    • timestamp - 兼作给定apikey的每条消息的唯一标识符

    • hash - apisecret时间戳的哈希值

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

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

    为了应对这种威胁,您可以做很多事情,具体取决于数据的 Value . Obfuscation 是一种简单的方法,可以更难以提取秘密 . 有一些工具可以帮到你,对Android来说更是如此,但你仍然必须拥有生成哈希的代码,而且技术娴熟的个人总是可以直接调用执行哈希的函数 .

    另一种减轻过度使用不需要登录的API的方法是对流量进行识别和阻止可疑IP地址 . 您想要的努力程度在很大程度上取决于您的数据的 Value .

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

相关问题