最佳做法的角度验证和授权不打破RESTful的原则是什么?

问题描述:

很长一段时间风扇,第一次海报:)

Long time fan, first time poster :)

我读过有关身份验证和授权使用REST和角度不少SO线程,但我还是没有感觉像我有什么,我希望做一个很好的解决方案。对于一些背景,我打算建设AngularJS一个应用程序,我想支持:

I've read quite a few SO threads about authentication and authorization with REST and Angular, but I'm still not feeling like I have a great solution for what I'm hoping to do. For some background, I'm planning to building an app in AngularJS where I want to support:


  1. 有限的来宾访问

  2. 要应用基于角色的访问一次验证

  3. 通过API认证

所有调用的REST API的将被要求通过SSL发生。我想这样做构建应用程序没有打破RESTful的原则,即不保持存储在服务器上的会话状态。在客户端的过程中,无论是进行相-一个可见的授权对服务器侧得到加强。因为我们需要与每个请求传递整个状态,我知道我需要通过某种象征,使后端服务器接收REST请求既可以验证和授权呼叫。

All of the calls to the REST API will be required to occur over SSL. I'd like to do build the app without breaking RESTful principles, namely not keeping session state stored on the server. Of course, whatever is done vis-a-vis authorization on the client-side has to be reinforced on the server side. Since we need to pass the entire state with each request, I know I need to pass some sort of token so that the backend server receiving the REST request can both authenticate and authorize the call.

随着中说,我的主要问题是各地的认证 - 在这里什么是最好的做法?似乎有很多讨论不同的方法,这里只是一小部分,我发现:

With that said, my main question is around authentication - what are the best practices here? It seems there are lots of different approaches discussed, here's just a few that I've found:

有一个类似的问题问(AngularJS最佳实践应用认证),但除非我误解了答案,这似乎暗示着一个服务器会话应该使用,这是打破RESTful的原则。

There was a similar question asked (AngularJS best practice application authentication), but unless I'm misunderstanding the answer, it seems to imply that a server session should be used, which is breaking RESTful principles.

我与亚马逊AWS和乔治·里斯文章主要关注的是它似乎假定消费者是一个程序,而不是最终用户。共享密钥可以发出提前一个程序员,那么谁可以用它来连接code调用在这里。这不是这里的情况 - 我需要调用从应用程序的REST API代表用户的

My main concern with the Amazon AWS and the George Reese article is it seems to assume that the consumer is a program, rather than an end user. A shared secret can be issued to a programmer in advance, who can then use it to encode calls here. This isn't the case here - I need to call the REST API from the app on behalf of the user.

请问这种做法是否足够?比方说,我有一个会话资源:

Would this approach be enough? Let's say I have a session resource:

POST / API /会话

为用户创建一个新的会话

Create a new session for a user

要创建一个会话,你需要张贴包含用户名和密码。

To create a session, you need to POST a JSON object containing the "username" and "password".

{
    "email" : "austen@example.com",
    "password" : "password"
}

卷曲示例

curl -v -X POST --data '{"username":"austen@example.com","password":"password"}' "https://app.example.com/api/session" --header "Content-Type:application/json"

响应

HTTP/1.1 201 Created {
    "session": {
        "id":"520138ccfa4634be08000000",
        "expires":"2014-03-20T17:56:28+0000"
    }
}

状态codeS


  • 201 - 创建,新的会话建立

  • 400 - 错误的请求,JSON对象是无效的或缺少所需信息

  • 401 - 未经授权,检查电子邮件/密码组合

  • 403 - 拒绝访问,禁用帐户或许可证无效

我要离开了为清楚起见,HATEOAS细节。在后端,将有创建并与用户相关联的新的,有限的持续时间的会话密钥。在随后的请求,我就可以通过这个作为HTTP头的一部分:

I'm leaving out the HATEOAS details for clarity. On the backend, there would be a new, limited duration session key created and associated with the user. On subsequent requests, I could pass this as part of the HTTP headers:

Authorization: MyScheme 520138ccfa4634be08000000 

然后,后端服务器将负责消化该出请求时,发现相关的用户和执行授权规则的请求。它可能应该更新会话的到期以及。

Then the backend servers would be responsible for digesting this out of the request, finding the associated user and enforcing authorization rules for the request. It should probably update the expiration for the session as well.

如果这一切是发生在SSL,我要离开的大门打开任何类型的,我应该保护免受攻击?你可以尝试猜测会话密钥,并将其放置在头,所以我想我可以另外追加的GUID会话密钥进一步prevent强力攻击的用户。

If all this is happening over SSL, am I leaving the door open to any kind of attacks that I should be protecting against? You could try to guess session keys and place them in the header, so I suppose I could additionally append a user GUID to the session key to further prevent brute force attacks.

这是一个几年,因为我已经积极地编程,我刚开始回摆在这里。道歉,如果我被钝或不必要地重新发明*,只是希望通过社会各界在这里根据我的阅读迄今为止运行我的想法,看看他们是否通过的试金石。预先感谢任何帮助/建议可以提供!

It's been a few years since I've actively programmed and I'm just getting back into the swing here. Apologies if I'm being obtuse or unnecessarily reinventing the wheel, just hoping to run my ideas by the community here based on my reading thus far and see if they pass the litmus test. Thanks in advance for any help/advice you can provide!

当有人问起关于REST的认证,我推迟到亚马逊网络服务和基本建议做。为什么?因为,从观点的群众的智慧,AWS解决问题,被大量使用,大量分析,通过了解和关心远远超过大多数是什么让比大多数安全要求审核人。和安全是一个好地方不是推倒重来。在肩膀站在而言,你可以比AWS做的差。

When someone asks about REST authentication, I defer to the Amazon Web Services and basically suggest "do that". Why? Because, from a "wisdom of the crowds" point of view, AWS solves the problem, is heavily used, heavily analyzed, and vetted by people that know and care far more than most about what makes a secure request than most. And security is a good place to "not reinvent the wheel". In terms of "shoulders to stand on", you can do worse than AWS.

现在,AWS不使用标记技术,而是使用基于共享秘密和有效载荷安全散列。它可以说是一个比较复杂的实现(及其所有正常化过程,等等)。

Now, AWS does not use a token technique, rather it uses a secure hash based on shared secrets and the payload. It is arguably a more complicated implementation (with all of its normalization processes, etc.).

但它的工作原理。

的缺点是,它需要应用程序保留的人共享秘密(即,密码),并且它也要求服务器存取的口令的一个纯文本版本。通常意味着该密码存储加密,然后将其解密为适当。而且还邀请更多的密钥管理和其他事情的复杂性,在服务器端VS安全散列技术。

The downside is that it requires your application to retain the persons shared secret (i.e. the password), and it also requires the server to have access to that a plain text version of the password. That typically means that the password is stored encrypted, and it then decrypted as appropriate. And that invite yet more complexity of key management and other things on the server side vs secure hashing technique.

最大的问题,当然,与任何令牌传递技术是中间人攻击,重放攻击。 SSL减轻这些居多,自然。

The biggest issue, of course, with any token passing technique is Man in the Middle attacks, and replay attacks. SSL mitigates these mostly, naturally.

当然,你也应该考虑的OAuth的家庭,有自己的问题,特别是互操作性,但如果这不是一个主要目标,那么技术肯定是有效的。

Of course, you should also consider the OAuth family, which have their own issues, notably with interoperability, but if that's not a primary goal, then the techniques are certainly valid.

有关你的应用程序,令牌租赁是不是一个大问题。您的应用程序仍然需要租用的时间框架内运作,或者能够延长。为了做到这一点,将需要或者保留用户凭证或重新提示他们它。只把令牌作为一个一流的资源,像其他任何东西。如果可行,尝试和其他的一些信息与请求关联和捆绑它的令牌(浏览器特征,IP地址),只是为了执行某些地方。

For you application, the token lease is not a big deal. Your application will still need to operate within the time frame of the lease, or be able to renew it. In order to do that it will need to either retain the user credential or re-prompt them for it. Just treat the token as a first class resource, like anything else. If practical, try and associate some other information with the request and bundle it in to the token (browser signature, IP address), just to enforce some locality.

您仍然开放的(潜在的)重播的问题,其中相同的请求可以被发送两次。具有典型的散列实现中,时间戳是能够置​​于括弧请求的寿命签名的一部分。这是在这种情况下,解决不同。例如,每个请求可以用序列号或GUID发送,您可以记录该请求已经被发挥到prevent它再次发生。不同的技术来的。

You are still open to (potential) replay problems, where the same request can be sent twice. With a typical hash implementation, a timestamp is part of the signature which can bracket the life span of the request. That's solved differently in this case. For example, each request can be sent with a serial ID or a GUID and you can record that the request has already been played to prevent it from happening again. Different techniques for that.