REST Web服务的身份验证

时间:2013-11-01 05:38:35

标签: web-services rest authentication oauth openid

我开始设计REST Web服务,并且不清楚最佳的身份验证方法。该服务将允许个人用户访问/管理他们自己的数据,因此需要某种类型的用户身份验证。我一直在看这些选项:

  • 的OAuth

OAuth似乎更多地是关于授权而不是身份验证。我计划在服务中本地处理授权,所以我不是在寻找解决方案。但是,OAuth是否也适用于身份验证?

  • 的OpenID

OpenID当然提供了身份验证的解决方案,但这更适合允许用户使用他们的第三方凭据(Google,Yahoo等)虽然我想支持这一点,但这不是我主要关注的问题,我肯定会允许用户使用本机凭据(电子邮件/密码)注册。

  • HTTP基本身份验证

这很容易实现,但我的理解是,这可能不是一种非常安全的方法。此外,它似乎需要为每次访问交换凭据,但我希望用户进行一次身份验证,然后通过会话令牌继续访问。

  • 自定义身份验证

基本上,滚动我自己的登录/令牌生成服务,并需要一个有效的令牌来访问所有其他资源(显然,一切都将通过SSL)。


除了创建Web服务之外,我还将构建一个代表用户使用这些服务的客户端(Web)应用程序,但我不希望应用程序必须存储用户信息/凭据/等等所以,像这样:

用户(使用电子邮件/密码或第三方凭据进行身份验证)    - > Web应用程序(使用应用程序ID进行身份验      - >网络服务

同样,我希望允许其他人也建立客户端,因此中间层可以是任何第三方应用程序:

用户(使用电子邮件/密码或第三方凭据进行身份验证)    - >第三方应用程序(使用应用程序ID进行身份验      - >网络服务

我的最高要求是:

  • 安全(显然)
  • 原生凭据
  • 支持第三方凭据(Google,Yahoo,LinkedIn等)
  • 支持多个客户端(网络应用,移动应用,第三方应用等)
  • 客户端凭据(只是应用ID?)
  • 到期的登录会话
  • 不需要授权

所以,我的问题是,基于上述情况(如果这太模糊,请告诉我),是否有“最佳”方法? OAuth或OpenID是否合适,或者我是否过于复杂,而应该只进行自己的身份验证?

修改

我想我需要实施以下内容:

1)原生凭证/令牌(通过SSL进行HTTP基本身份验证?)

2)OpenID“依赖方”允许我的api使用其他地方托管的OpenID(即“支持第三方凭证”)

3)OAuth“Consumer”允许我的api访问第三方服务(比如访问用户的LinkedIn个人资料)。

4)一个OpenID“提供者”,允许人们在别处使用api的本地ID(可选)

5)OAuth“提供商”允许第三方应用代表用户访问我的API(可选)

这看起来是对的,还是我让它变得比它需要的更复杂?

8 个答案:

答案 0 :(得分:12)

你可以考虑使用JWT(JSON Web Token)JWT draft rfc。它肯定会满足您的安全性和会话到期要求。然而,作为草案标准,它现在不太可能被广泛使用,这可能会很快改变,因为JWT是OAuth 2.0的一部分。 JWT很容易在大多数语言中实现,并且已经有很多库。作为一个简单的解释,JWT令牌由3个部分组成,即标题,正文和签名。标题和正文是json对象,它们是basee64url编码的(字母表与base64的2个最后字符不同),然后用HMAC256(或标题中指定的其他算法)签名,RFC解释了如何准确生成此签名。您可能需要查看此online token generator

JWT是http标头和查询参数友好。

答案 1 :(得分:11)

要考虑的一个好选择是“共享密钥身份验证”。这是Amazon Web服务和Windows Azure存储服务使用的身份验证类型。我们在我们开发的REST服务中使用了共享密钥身份验证。您可以在Google上快速搜索“共享密钥身份验证”,您将获得大量详细信息。

我写了一篇关于此事的博文here

高级步骤是:

  1. 客户端组合了REST服务定义的一组唯一数据(元素)。
  2. 使用仅为客户端和REST服务所知的密钥对此组合数据进行签名
  3. 将此签名作为HTTP标头的值
  4. 发送到REST服务
  5. REST服务计算签名的方式与客户端完全相同
  6. 将客户端发送的签名与计算出的签名进行比较,如果相同则假定其有效请求,否则拒绝请求

答案 2 :(得分:7)

我的建议是验证第一个请求,然后设置会话令牌。

前端应用程序将存储令牌并为每个后续请求提供令牌。

令牌将有一个到期时间。如果在一段时间内没有使用,令牌将过期。

令牌可以与原始IP地址相关联,以增加安全性。

令牌可以作为cookie传输,也可以作为URL中的查询参数之一传输。

如果可以接受SSL客户端身份验证的麻烦,则可以使用相互SSL身份验证。必须为每个客户端配置服务器信任的证书。如果您必须以不同方式对待客户,它可以是相同的证书或不同的证书。

答案 3 :(得分:2)

根据您的要求,我认为OAuth 2.0实际上可能是一个有趣的选择。 OAuth确实是一种授权协议,但Authenticates客户端clientIdclientSecret。您可以使用Client Credential Flow并选择不包含Refresh Token,这样用户就有Access Token,这会在一段时间后过期。由于OAuth是一种广泛使用的协议,因此它们已经有许多客户端和服务器端库供您和您的客户使用。

如果您认为OAuth太重或太复杂而无法应用,我可能会坚持使用Basic Authentication而不是HTTPS。但正如我在另一个类似问题的答案中所述,我绝不会发明自己的身份验证机制。

有关详细信息,您还可以查看我之前提到的另一个类似问题的答案:https://stackoverflow.com/a/15003777/849741

答案 4 :(得分:1)

您可以使用HTTP Basic Auth,其中转移的密码实际上不是密码而是令牌,客户端在不同的资源请求上获取,其中他/她/它必须提供他/她/其密码一次,只有一次(甚至可能在不同的频道上)。这不能保证中间人攻击(因为没有消息签名),但想法是,你总是可以要求客户端以某种方式生成动态令牌(即在你的身份验证服务上)然后让它将该令牌作为密码替换发送,因此实际密码不会经常通过线路传输。 是的,这看起来像是#34;自定义身份验证解决方案之一,但它实际上并不是因为您可以在令牌密码上强加您想要的规则,例如使用签名令牌作为密码这是在每个请求上进行会话绑定或重新计算(不共享任何机密),因此服务器可以验证消息 - 您的需求是什么。我们的想法是将验证令牌作为"密码" HTTP Basic Auth请求并不依赖于更复杂的协议,而不是将其排除在外(根据您的选择)。

答案 5 :(得分:1)

我已经实现并发布了一个允许身份验证的基本服务作为开源,它可以很容易地更改为允许3元组登录(如果需要)。它大约有2年的历史,用Java编写,因此你可能想重新考虑这项技术,但是它可以运行,你可以了解它是如何完成的。找到它here on google,或关注my blog posts。请注意,该应用不再加载到云端,但如果您在帐户中设置该应用,则一切正常。

答案 6 :(得分:0)

我建议您使用Spring Boot作为RESTful Web服务,因为您可以使用他们的Spring Security根据他们的模板实现您自己的自定义身份验证。您可以通过分别扩展或实现其基本安全性类和接口来实现自己的自定义身份验证。如果需要,您还可以选择合并您在Spring Boot中列出的其他auth机制。

答案 7 :(得分:0)

如果只需要授权,可以使用

OAuth 2.0 。可以使用OpenID Connect,它提供身份验证并支持OAuth2.0进行授权。对于OepnID Connect,如果您需要自己设置服务,则可以使用许多认证产品,也可以使用许多在线服务。