REST Web服务的身份validation
我开始devise一个REST Web服务,并且对最佳的身份validation方法还不清楚。 该服务将允许个人用户访问/pipe理他们自己的数据,因此需要某种types的用户authentication。 我一直在看这些选项:
- OAuth的
OAuth似乎更多是关于授权而不是authentication。 我打算在服务内部原生地处理授权,所以我不在寻找解决scheme。 但是,OAuth是否也适用于身份validation?
- OpenID的
OpenID当然提供了一个authentication解决scheme,但是这更多的是允许用户使用他们的第三方证书(Google,Yahoo等)。虽然我想支持这个,但这不是我主要关心的,我会绝对允许用户注册本机凭据(电子邮件/密码)。
- HTTP基本authentication
这很容易实现,但我的理解是,这可能不是一个非常安全的方法。 此外,它似乎需要交换每个访问凭据,但我宁愿用户authentication一次,然后通过会话令牌继续访问。
- 自定义authentication
基本上,滚动我自己的login/令牌生成服务,并要求一个有效的令牌访问所有其他资源(显然,一切都会通过SSL)。
除了创buildWeb服务外,我还将构build一个代表用户使用这些服务的客户端(Web)应用程序,但我不希望应用程序必须存储用户信息/凭证等。 所以,这样的事情:
用户(使用电子邮件/密码或第三方凭据进行身份validation) – > Web应用程序(使用应用程序ID进行身份validation) – > Web服务
再次,我想允许其他人也build立客户,所以中间层可以是任何第三方应用程序:
用户(使用电子邮件/密码或第三方凭据进行身份validation) – >第三方应用程序(使用应用程序ID进行身份validation) – > Web服务
我的最高要求是:
- 安全(显然)
- 原生凭据
- 支持第三方凭证(Google,Yahoo,LinkedIn等)
- 支持多个客户端(networking应用程序,手机应用程序,第三方应用程序等)
- 客户端凭据(只是一个应用程序ID?)
- login会话过期
- 授权是不需要的
所以,我的问题是,基于上述(请让我知道这是否太模糊),有没有一个“最好”的方法? OAuth或OpenID是否合适,还是我这样做太复杂,而应该推出我自己的身份validation?
编辑:
我想我将需要实施以下内容:
1)原生凭证/令牌(基于SSL的HTTP基本身份validation?)
2)OpenID“依赖方”允许我的api使用其他地方托pipe的OpenID(即“支持第三方凭证”)
3)OAuth“消费者”,允许我的API访问第三方服务(如访问用户的LinkedIn个人资料)。
4)OpenID“提供者”,允许用户在其他地方使用api的本地ID(可选)
5)OAuth“供应商”,允许第三方应用程序代表用户访问我的api(可选)
这似乎是正确的,还是我做这比它需要更复杂?
你可以考虑JWT(JSON Web Token),参见JWT draft rfc 。 它肯定会满足您的安全和会话到期要求。 然而,作为一个标准草案,目前不太可能被广泛使用,因为JWT是OAuth 2.0的一部分,所以这可能会很快改变。 JWT很容易在大多数语言中实现,并且已经有很多库。 作为一个简单的解释,一个JWT令牌由3部分组成,头部,主体和签名。 标题和正文是被basee64url编码的json对象(字母与base64的最后两个字符不同),然后用HMAC256(或标题中指定的另一个algorithm)签名,RFC解释了如何准确地生成这个签名。 您可能需要检查此在线令牌生成器 。
JWT是http头和查询参数友好。
其中一个好的select是“共享密钥validation”。 这是Amazon Web服务和Windows Azure存储服务使用的身份validationtypes。 我们在我们开发的REST服务中使用了共享密钥authentication。 您可以在Google上快速search“共享密钥身份validation”,您将获得很多详细信息。
我在这里写了一篇博文。
高层次的步骤是:
- 客户端结合了由REST服务定义的一组唯一的数据(元素)。
- 使用只有客户端和REST服务已知的密钥签署此组合数据
- 将此签名作为HTTP Header的值发送到REST服务
- REST服务与客户端完全一样地计算签名
- 比较客户端发送的签名和计算出的签名,如果相同,则认为其有效请求,否则拒绝该请求
我的build议是validation第一个请求,然后设置一个会话令牌。
前端应用程序将存储该令牌并为其提供每个后续请求。
令牌将有一个到期时间。 如果某个时期没有使用,令牌将过期。
令牌可以与发起IP地址相关联以增加安全性。
令牌可以作为cookie传送,也可以作为URL中的查询参数之一传送。
如果SSL客户端身份validation的麻烦是可以接受的,则可以使用相互SSL身份validation。 每个客户端都必须配备服务器信任的证书。 它可以是相同的证书,或者不同的证书,如果你必须以不同的方式处理客户。
根据您的要求,我认为OAuth 2.0
实际上可能是一个有趣的选项。 OAuth确实是一个授权协议,但它也使用clientId
和clientSecret
对客户端进行Authenticates
。 您可以使用Client Credential Flow
并select不包含Refresh Token
,这样用户具有Access Token
,该Access Token
会在一段时间后过期。 而且由于OAuth是一个被广泛使用的协议,它们已经为您和您的客户使用了许多客户端和服务器端库。
如果您认为OAuth对您的应用程序太重或太复杂,我可能会坚持使用基于HTTPS
Basic Authentication
。 但正如我在另一个类似问题的答案中所说的,我绝不会发明自己的authentication机制。
有关更多信息,您也可以查看我之前给出的类似问题的其他答案: https : //stackoverflow.com/a/15003777/849741
您可以使用HTTP基本身份validation,其中被转移的密码实际上不是密码,而是一个令牌,客户端通过不同的资源请求获取,他/她必须只提供一次(或一次)提供其密码甚至可能通过不同的渠道)。 这不能保证中间人攻击(因为没有消息签名),但是这个想法是,你总是可以要求客户端以某种方式生成一个dynamic令牌(即在你自己的auth服务上),然后它发送该令牌作为密码replace,所以实际的密码不会不断地通过电线传输。 是的,这看起来像是“自定义authentication解决scheme”之一,但实际上并不是因为您可以在令牌密码上施加任何您想要的规则,例如使用签名令牌作为会话绑定或重新计算的密码在每个请求(不分享任何秘密),所以服务器可以validation消息 – 你的需求是什么。 我们的想法是将validation令牌作为HTTP基本validation请求的“密码”发送,而不是依赖更复杂的协议,而不是依据这些协议排除(根据您的select)。
我已经实现并发布了一个基本的服务,允许身份validation,它可以很容易地更改为允许三元组login,如果需要。 它已经有2年的历史,并且是用Java编写的,所以你可能想重新考虑一下这个技术,但是它可以工作,并且你可以得到如何完成的基本思想。 在谷歌上find它,或者关注我的博客文章 。 请注意,该应用程序不再加载在云端,但如果你在你的账户上设置,所有应该没问题。
我build议使用Spring Boot作为您的REST风格的Web服务,因为那样您就可以使用他们的Spring Security来基于他们的模板实现您自己的自定义authentication。 您可以通过分别扩展或实现其基本安全类和接口来实现自己的自定义身份validation。 如果需要,还可以select将Spring Boot中列出的其他身份validation机制合并到一起。