RESTfulauthentication

RESTfulauthentication是什么意思,它是如何工作的? 我无法在Google上find一个好的概述。 我唯一的理解是,你在URL中传递会话密钥(remeberal),但这可能是非常错误的。

如何在RESTful客户端 – 服务器体系结构中处理authentication是一个有争议的问题。

通常,可以通过以下方式在SOA over HTTP世界中实现:

  • 基于HTTPS的HTTP基本authentication;
  • Cookies和会话pipe理;
  • HTTP标头中的令牌(例如OAuth 2.0);
  • 使用附加签名参数查询身份validation

你必须适应,甚至更好地混合这些技术,才能最好地匹配你的软件架构。

每个身份validationscheme都有自己的PRO和CON,具体取决于您的安全策略和软件体系结构的用途。

基于HTTPS的HTTP基本authentication

基于标准HTTPS协议的第一种解决scheme被大多数Web服务所使用。

GET /spec.html HTTP/1.1 Host: www.example.org Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== 

它很容易实现,默认情况下在所有的浏览器上都可用,但是有一些已知的缺点,比如浏览器上显示的糟糕的authentication窗口(这里没有LogOut-likefunction),一些服务器端的附加CPU消耗,以及用户名和密码通过HTTPS传输到服务器的事实(在键盘input期间,让密码仅保留在客户端,应该更安全,并且作为安全哈希存储在服务器)。

我们可能使用摘要式身份validation ,但它也需要HTTPS,因为它容易受到MiM或Replay攻击,并且特定于HTTP。

通过Cookie进行会话

说实话,在服务器上pipe理的会话并不是真正的无状态的。

一种可能是维护cookie内容中的所有数据。 并且,通过devise,cookie在服务器端被处理(客户端实际上甚至不尝试解释这个cookie数据:它只是在每个连续的请求中把它交给服务器)。 但是这个cookie数据是应用程序状态数据,因此客户端应该在纯粹的无状态世界中pipe理它,而不是服务器。

 GET /spec.html HTTP/1.1 Host: www.example.org Cookie: theme=light; sessionToken=abc123 

Cookie技术本身是HTTP链接的,所以它不是真正的RESTful,它应该是协议无关的,恕我直言。 它容易受到MiM或Replay攻击。

授予通过令牌(OAuth2)

另一种方法是在HTTP标头中放置一个标记,以便对请求进行身份validation。 例如,这就是OAuth 2.0的function。 请参阅RFC 6749 :

  GET /resource/1 HTTP/1.1 Host: example.com Authorization: Bearer mF_9.B5f-4.1JqM 

简而言之,这与Cookie非常相似,并且存在相同的问题:不是无状态的,依赖于HTTP传输细节,并受到许多安全弱点 (包括MiM和Replay)的影响,因此只能通过HTTPS使用。

查询authentication

查询authentication包括通过URI上的一些附加参数对每个RESTful请求进行签名。 看到这篇参考文章 。

它在这篇文章中被定义为:

所有REST查询都必须通过使用专用凭证作为签名令牌对按小写字母顺序排列的查询参数进行签名进行身份validation。 签名应在URL编码查询string之前进行。

这种技术可能与无状态体系结构更兼容,也可以使用轻量级会话pipe理(使用内存中会话而不是DB持久性)来实现。

例如,下面是上面链接的一个通用的URI示例:

 GET /object?apiKey=Qwerty2010 

应该如此传输:

 GET /object?timestamp=1261496500&apiKey=Qwerty2010&signature=abcdef0123456789 

被签名的string是/object?apikey=Qwerty2010&timestamp=1261496500 ,签名是使用API​​密钥的私有组件的string的SHA256哈希值。

服务器端数据caching可以始终可用。 例如,在我们的框架中,我们将响应caching在SQL级别,而不是在URI级别。 所以添加这个额外的参数不会中断caching机制。

有关基于JSON和REST的客户机/服务器ORM / SOA / MVC框架中的RESTfulauthentication的详细信息,请参阅本文 。 由于我们不仅允许通过HTTP / 1.1进行通信,而且还允许通信(本地)命名pipe道或GDI消息,所以我们试图实现一个真正的RESTfulauthentication模式,而不是依赖HTTP特性(如头或cookie)。

实际上,即将到来的OAuth 2.0的MAC令牌authentication在“授权令牌”当前scheme方面可能是巨大的改进。 但是这仍然是一个正在进行的工作,并且与HTTP传输有关。

结论

值得一提的是,REST不仅是基于HTTP的,即使在实践中,它大部分都是通过HTTP实现的。 REST可以使用其他通信层。 所以RESTfulauthentication不仅仅是HTTPauthentication的同义词,无论Google如何回答。 它甚至不应该使用HTTP机制,而应该从通信层中抽象出来。

我真的怀疑那些踊跃喊“HTTP身份validation”的人是否曾尝试用REST制作一个基于浏览器的应用程序(而不是机器对机器的Web服务)(没有任何意图 – 我只是觉得他们没有面对复杂的问题)。

在浏览器中使用生成HTML页面的RESTful服务使用HTTP身份validation时发现的问题是:

  • 用户通常会得到一个丑陋的浏览器制作的login框,这非常不利于用户。 你不能添encryption码检索,帮助框等。
  • 注销或以不同的名称login是一个问题 – 浏览器将继续向站点发送身份validation信息,直到您closures该窗口
  • 超时是困难的

一个非常有洞察力的文章, 在这里逐点解决这个问题,但是这导致了很多浏览器特定的JavaScript hackery,解决方法变通办法等等。 因此,它也不是向前兼容的,因此在新的浏览器被释放时将需要不断的维护。 我不认为这个devise干净清晰,加上我觉得这是很多额外的工作和头痛,所以我可以热情地向我的朋友展示我的REST徽章。

我相信cookies是解决scheme。 但是,等一下,cookies是邪恶的,不是吗? 不,他们不是,曲奇饼的使用方式往往是邪恶的。 Cookie本身只是客户端信息的一部分,就像浏览器在浏览时将跟踪的HTTP身份validation信息一样。 这个客户端信息在每次请求时都会被发送到服务器,就像HTTPauthentication信息一样。 从概念上讲,唯一的区别就是这个客户端状态的内容可以由服务器决定作为响应的一部分。

通过以下规则将会话设置为RESTful资源:

  • 会话将密钥映射到用户标识(可能还有超时的最后一个操作时间戳)
  • 如果会话存在,那就意味着密钥是有效的。
  • login意味着POST /到会话,一个新的密钥被设置为一个cookie
  • 注销表示DELETEing / sessions / {key}(POST超载,请记住,我们是浏览器,HTML 5还有很长的路要走)
  • 身份validation是通过在每个请求中将密钥作为cookie发送并检查会话是否存在并且有效来完成的

与HTTP身份validation的唯一区别是,身份validation密钥由服务器生成,并发送给持续发送的客户端,而不是由客户端从input的凭据计算。

converter42补充说,当使用https(我们应该)时,cookie的安全标志设置很重要,这样authentication信息永远不会通过非安全连接发送。 伟大的一点,没有看到它自己。

我觉得这是一个很好的解决scheme,但是我必须承认,我不够安全专家来发现这个scheme中的潜在漏洞 – 我所知道的是,数百个非REST风格的Web应用程序基本上使用相同的login协议($ _SESSION inphp,Java EE中的HttpSession等)。 Cookie头内容仅用于寻址服务器端资源,就像接受语言可能用于访问翻译资源等。 我觉得这是一样的,但也许别人没有? 你觉得呢,伙计?

关于这个话题已经足够了,这里的好人。 但这是我的2美分。

有两种交互模式:

  1. 人机对话(HTM)
  2. 机器对机器(MTM)

该机器是公用分母,表示为REST API,而演员/客户机是人或机器。

现在,在一个真正的RESTful体系结构中,无状态的概念意味着每个请求都必须提供所有相关的应用程序状态(即客户端状态)。 通过相关,这意味着REST API可以处理请求并提供适当的响应。

当我们在人机交互的应用环境中考虑这个问题的时候,就像Skrebbel在上面指出的那样,“浏览器为基础”意味着在浏览器中运行的(web)应用程序需要发送它的状态和相关信息使得后端REST API成为可能。

考虑一下:你有一个公开的数据/信息平台作为一套REST API。 也许你有一个自助服务BI平台来处理所有的数据立方体。 但是,您希望您的(人)客户通过(1)Web应用程序,(2)移动应用程序和(3)某个第三方应用程序访问此应用程序。 最后,甚至连锁MTM导致HTM – 正确。 所以,用户仍然处于信息链的顶端。

在前两种情况下,您有一个人机交互的情况,这些信息实际上是由用户使用的。 在最后一种情况下,您有一个使用REST API的机器程序。

身份validation的概念适用于所有人。 您将如何devise这个,以便您的REST API以统一,安全的方式访问? 我看到这个的方式有两种方法:

方式1:

  1. 没有login开始。 每个请求都执行login
  2. 客户端发送其标识参数+请求特定参数与每个请求
  3. REST API带着它们,转身,ping用户存储(不pipe是什么)并确认auth
  4. 如果auth已经build立,则为请求提供服务; 否则,用适当的HTTP状态码拒绝
  5. 对您的目录中所有REST API的每个请求重复上述操作

方法2:

  1. 客户端以validation请求开始
  2. loginREST API将处理所有这样的请求
  3. 它需要身份validation参数(API密钥,uid /密码或任何您select的),并validation用户存储(LDAP,AD或MySQL DB等)的身份validation。
  4. 如果validation,创build一个身份validation令牌,并交还给客户端/调用者
  5. 然后调用者将这个authentication令牌+请求特定参数发送到其他业务REST API的每个后续请求,直到注销或直到租约到期

显然,在Way-2中,REST API将需要一种方法来识别和信任令牌。 Login API执行身份validationvalidation,因此您的目录中的其他REST API需要信任“代理钥匙”。

这当然意味着authentication密钥/令牌将需要在REST API之间进行存储和共享。 这个共享的可信任令牌库可以是本地/联合的,允许其他组织的REST API互相信任。

但是我离题了。

关键是,需要维护和共享“状态”(关于客户端的身份validation状态),以便所有REST API都可以创build一个信任圈。 如果我们不这样做,那就是Way-1,我们必须接受一个authentication行为,必须对所有进入的请求执行。

执行身份validation是一个资源密集的过程。 想象一下,执行SQL查询,针对每个传入的请求,针对您的用户存储检查uid / pwd匹配。 或者,encryption并执行哈希匹配(AWS风格)。 在架构上,每个REST API都需要执行此操作,我怀疑是使用通用的后端login服务。 因为,如果你不这样做,那么你到处乱扔authentication码。 一大堆烂摊子

所以更多的层次,更多的延迟。

现在,采取Way-1并应用于HTM。 你的(人类)用户是否真的关心你是否需要发送uid / pwd / hash或其他什么? 不,只要你不打扰她每秒钟的身份validation/login页面。 如果你有客户,祝你好运。 所以,你要做的是将login信息存储在客户端的某个地方,在浏览器中,在开始的时候,把每一个请求发送出去。 对于(人)用户,她已经login,并且“会话”可用。 但实际上,她是每一个请求authentication。

和Way-2一样。 你的(人)用户永远不会注意到。 所以没有害处。

如果我们将Way-1应用于MTM,该怎么办? 在这种情况下,因为它是一台机器,所以我们可以通过要求它提交每个请求的authentication信息来让这个人失望。 没人在乎! 在MTM上执行Way-2不会引起任何特殊的反应, 它是一个该死的机器。 它可以小心!

所以真的,问题是什么适合你的需要。 无国籍有代价。 付出代价,继续前进。 如果你想成为一个纯粹主义者,然后付出代价,继续前进。

最后,哲学并不重要。 真正重要的是信息发现,呈现和消费体验。 如果人们喜欢你的API,你做了你的工作。

这是一个真正完整的RESTfulauthentication解决scheme:

  1. 在authentication服务器上创build一个公钥/私钥对。
  2. 将公钥分配给所有服务器。
  3. 当客户authentication时:

    3.1。 发出一个令牌,其中包含以下内容:

    • 到期时间
    • 用户名(可选)
    • 用户IP(可选)
    • 密码散列(可选)

    3.2。 用私钥encryption令牌。

    3.3。 将encryption的令牌发回给用户。

  4. 当用户访问任何API时,他们也必须通过他们的authentication令牌。

  5. 服务器可以通过使用auth服务器的公钥来validation令牌是否有效。

这是无状态/ RESTfulauthentication。

请注意,如果包含密码散列,则用户还会将未encryption的密码与身份validation令牌一起发送。 服务器可以通过比较散列validation密码是否与用于创build身份validation令牌的密码相匹配。 使用类似HTTPS的安全连接将是必要的。 客户端的Javascript可以处理获取用户的密码,并将其存储在客户端,无论是在内存中还是在cookie中,都可能使用服务器的公钥encryption。

说实话,我已经在这里看到了很好的答案,但是让我困扰的是,有人会把整个无状态的概念带到极端的教条。 这让我想起那些只想拥抱纯粹面向对象的老傻瓜粉丝,如果事情不是一个对象,那么你做错了。 不要烦我。

RESTful方法应该让你的生活变得更轻松,减less会话的开销和成本,尽量遵循它,因为这是一个明智的做法,但是一分钟你遵循一个纪律(任何纪律/指导)到极端的地方不再提供它打算的好处,那么你做错了。 今天的一些最好的语言既有function编程,也有面向对象。

如果解决问题的最简单方法是将身份validation密钥存储在cookie中,并将其发送到HTTP头上,那么请执行此操作,不要滥用它。 请记住,如果所有的会话都是由一个包含密钥的短string组成的,那么会话就会变得很糟糕,那么最重要的是什么?

我很乐意接受修改意见,但是我只是没有看到让我们的生活变得悲惨的一点,就是避免在我们的服务器上保留一个大的哈希字典。

首先,一个REST风格的Web服务是STATELESS (或换句话说, SESSIONLESS )。 因此,一个RESTful服务没有,也不应该有涉及会话或cookie的概念。 在RESTful服务中执行身份validation或授权的方法是使用RFC 2616 HTTP规范中定义的HTTP授权标头。 每个请求都应该包含HTTP授权标头,并且该请求应该通过HTTP(SSL)连接发送。 这是执行身份validation并validationHTTP RESTful Web服务中的请求授权的正确方法。 我在思科系统公司为思科PRIME Performance Manager应用程序实施了一个RESTful Web服务。 作为该Web服务的一部分,我也实施了authentication/授权。

鲁本斯·戈麦斯。

这当然不是关于“会话密钥”,因为它通常用来指代在REST的所有约束中执行的无会话authentication。 每个请求都是自描述的,携带足够的信息来自行授权请求,而无需任何服务器端应用程序状态。

最简单的方法是从RFC 2617中的 HTTP内置authentication机制开始。

@skrebel( http://www.berenddeboer.net/rest/authentication.html )提到的“非常有洞察力”的文章讨论了一个令人费解的但真正破坏的身份validation方法。

您可以尝试访问该页面(该页面应该只能用于已validation的用户),而不需要任何login凭证即可访问http://www.berenddeboer.net/rest/site/authenticated.html

(对不起,我不能评论答案)

我会说REST和身份validation根本不混合。 REST意味着无状态,但“authentication”是一个状态。 你不能让他们在同一层。 如果你是一个RESTful的倡导者,并对国家皱眉,那么你必须去与HTTPS(即把安全问题的另一层)。

I think restful authentication involves the passing of an authentication token as a parameter in the request. Examples are the use of apikeys by api's. I don't believe the use of cookies or http auth qualifies.

That's the way to do that: Using OAuth 2.0 for Login .

You may use other authentication methods other then Google's as long as it supports OAuth.

I think the following approach can be used for REST service authentication:

  1. Create a login RESTful API to accept username and password for authentication. Use HTTP POST method to prevent caching and SSL for security during transit On successful authentication, the API returns two JWTs – one access token (shorter validity, say 30 minutes) and one refresh token (longer validity, say 24 hours)
  2. The client (a web based UI) stores the JWTs in local storage and in every subsequent API call passes the access token in "Authorization: Bearer #access token" header
  3. The API checks the validity of the token by verifying the signature and expiry date. If the token is valid, check if the user (It interprets the "sub" claim in JWT as username) has access to the API with a cache lookup. If the user is authorized to access the API, execute the business logic
  4. If the token is expired, the API returns HTTP response code 400
  5. The client, on receiving 400/401, invokes another REST API with the refresh token in "Authorization: Bearer #refresh token" header to get a new access token.
  6. On receiving the call with refresh token, check if the refresh token is valid by checking the signature and the expiry date. If the refresh token is valid, refresh the access right cache of the user from DB and return access token. If the refresh token is invalid, return HTTP response code 400
  7. If a new access token is returned, go to step 2. If HTTP response code 400 is returned, the client assumes that the refresh token has expired and asks for username and password from the user
  8. For logout, purge the local storage

With this approach we are doing the expensive operation of loading the cache with user specific access right details every 30 minutes. So if an access is revoked or new access is granted, it takes 30 minutes to reflect or a logout followed by a login

To answer this question from my understanding…

An authentication system that uses REST so that you do not need to actually track or manage the users in your system. This is done by using the HTTP methods POST, GET, PUT, DELETE. We take these 4 methods and think of them in terms of database interaction as CREATE, READ, UPDATE, DELETE (but on the web we use POST and GET because that is what anchor tags support currently). So treating POST and GET as our CREATE/READ/UPDATE/DELETE (CRUD) then we can design routes in our web application that will be able to deduce what action of CRUD we are achieving.

For example, in a Ruby on Rails application we can build our web app such that if a user who is logged in visits http://store.com/account/logout then the GET of that page can viewed as the user attempting to logout. In our rails controller we would build an action in that logs the user out and sends them back to the home page.

A GET on the login page would yield a form. a POST on the login page would be viewed as a login attempt and take the POST data and use it to login.

To me, it is a practice of using HTTP methods mapped to their database meaning and then building an authentication system with that in mind you do not need to pass around any session id's or track sessions.

I'm still learning — if you find anything I have said to be wrong please correct me, and if you learn more post it back here. 谢谢。

Using a Public key infrastruction in which the registration of a key involves proper binding ensures that the public key is bound to the individual to which it is assigned in a way that ensures non-repudiation

See http://en.wikipedia.org/wiki/Public_key_infrastructure . If you follow the proper PKI standards, the person or agent who improperly uses the stolen key can be identified and locked out. If the agent is required to use a certificate, the binding gets pretty tight. A clever and quick-moving thief can escape, but they leave more crumbs.