确保REST API的安全而不用费吹灰之力


73

在设计REST API时,通常先对用户进行身份验证吗?

我正在寻找的典型用例是:

  • 用户想要获取数据。当然,我们喜欢分享!获取公共API密钥并阅读!
  • 用户想要存储/更新数据...等等!你是谁,你能做到吗?

我想一次构建它,并允许说一个Web应用程序,一个Android应用程序或一个iPhone应用程序来使用它。

REST API似乎是符合此类要求的合理选择

为了说明我的问题,我将使用一个简单的示例。

我在数据库中有一个项目,该项目具有等级属性(1到5的整数)。

如果我正确理解REST,则将使用我选择的返回CSV,XML或JSON的语言来实现GET请求,如下所示:

http://example.com/product/getrating/{id}/

假设我们选择JSON,我们返回:

{
  "id": "1",
  "name": "widget1",
  "attributes": { "rating": {"type":"int", "value":4} }
}

这对于面向公众的API很好。我明白了。

我有很多问题要问,如何将其与安全模型结合起来?我习惯了Web应用程序安全性,在该状态下,我始终具有标识用户的会话状态,因此无论他们决定发送给我什么,我都可以控制他们可以做什么。据我了解,这不是RESTful的,因此在这种情况下将是一个不好的解决方案。

我将尝试使用相同项目/等级的另一个示例。

如果用户“JOE”希望将添加评级项目

可以使用以下方法完成:

http://example.com/product/addrating/{id}/{givenRating}/

在这一点上,我想存储表示“ JOE”给予产品{id}等级为{givenRating}的数据。

问题:我怎么知道请求来自“ JOE”而不是“ BOB”。

此外,如果要获取更敏感的数据(例如用户的电话号码)怎么办?

到目前为止,我得到的是:

1)使用HTTP的内置功能对每个请求(纯HTTP或HTTPS)进行身份验证。

这意味着现在每个请求都采用以下形式:

https://joe:joepassword@example.com/product/addrating/{id}/{givenRating}/

2)使用带有私钥和公钥的Amazon S3之类的方法:http : //www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication/

3)无论如何都要使用cookie并破坏REST的无状态部分。

第二种方法对我来说似乎更好,但我想知道我是否真的必须重新发明整个东西?自己哈希,存储,生成密钥等?

这听起来很像在典型的Web应用程序中使用会话并自己重写整个堆栈,这对我来说通常意味着“您做错了”,尤其是在处理安全性时。

编辑:我想我也应该提到OAuth。


4
如果您在每次请求时都发送用户名和密码,请使用HTTPS
马特·鲍尔

52
与安全无关,但不会使用RESTful API getratingand andrating; 它只是rating,您将对该资源进行GET,POST,PUT或DELETE。
邓肯

Answers:


21

五年后编辑

使用OAuth2!

先前版本

不,绝对没有必要使用Cookie。它的安全性不如HTTP Digest,OAuth或Amazon的AWS(很难复制)。

您查看Cookie的方式是,它是与Basic / Digest / OAuth /一样多的身份验证令牌,但不太合适。

但是,只要会话cookie的内容不影响您从服务器返回的资源的内容,我就不会觉得使用cookie本身就违反了RESTful原则。

Cookies是邪恶的,请停止使用它们。


2
我发现每个人说的话很难复制Amazon的方式……就像我没有发现从头开始编写JavaScript那样“辛苦”,但是jQuery肯定有助于很好地编写它。阅读有关内容后,我很想知道是否没有一个抽象的框架?
jfrobishow 2011年

1
去谷歌上查询。我为AWS写了一个实现,但我认为它还不完整:code.google.com/p/sabredav/source/browse/lib/Sabre/HTTP/…–
Evert

2
抱歉,答案不正确。Cookies和HTTP Digest是互补但正交的-您可以使用第二个来验证用户身份并发出Cookie。与OAuth相比,当您拥有跨域服务时,或者正在让其他不受信任的人将客户端写入您的服务(涉及的第三方)并希望允许您的用户撤消应用程序访问权限时,基于cookie的安全性将无法使用。但是在其他情况下,它的工作原理与OAuth完全相同,您可以将cookie视为OAuth访问令牌,这也需要将其存储在某个地方。
zihotki 2015年

我的答案写在OAuth2之前,当时每个OAuth令牌都是与该请求相关的一堆信息的摘要。对于OAuth2承载者而言,情况并非如此,实际上,它实际上与Cookie中的令牌相当。
Evert

21

不必担心成为“ RESTful”,而担心安全性。这是我的方法:

步骤1:用户使用凭据访问身份验证服务。

步骤2:如果凭证已签出,请返回指纹,会话ID等,然后将它们弹出到共享内存中以供日后快速检索;如果您不介意将几毫秒添加到Web服务周转时间中,则可以使用数据库。

步骤3:在每个Web服务脚本的顶部添加一个入口点调用,以验证每个Web服务请求的指纹和会话ID 。

步骤4:如果指纹和会话ID无效或超时,则重定向到身份验证。

读这个:

RESTful身份验证


3
但是,难道不是每次“会话”过期时都强制用户在访问API之前登录吗?如果使用移动设备,您该怎么办?给他们一个永久的“密钥”,这样他们在使用应用程序使用API​​时不必每次都登录吗?
jfrobishow 2011年

1
我强迫他们登录。要么就是使用Cookie,要么将指纹映射到他们的UDID,但是UDID意味着用户必须从同一设备访问服务。
丹尼尔·佩雷拉

关于步骤3:这意味着如果我使用的MVC框架在“ Controllers”中使用“ Actions”,我应该在每个Action中添加两个额外的参数(指纹和sessionid)吗?
体育

@sports关于在方法调用开始时添加功能:如果使用的是MVC / WebApi,请使用OWIN拦截操作。如果要允许任何东西通过Endint,但想保护域逻辑,请使用PostSharp之类的AOP。如果要自己动手,则只需使用Attributes并打破一堆原则,即可在要保护的方法的属性中添加功能。
Suamere

8

三年后编辑

我完全同意Evert,使用OAuth2与HTTPS结合,不要重蹈覆辙!:-)

通过更简单的REST API-不适用于第三方客户端-JSON Web令牌也可以很好。

先前版本

无论如何都要使用cookie并破坏REST的无状态部分。

不要使用会话,使用会话时,您的REST服务将无法很好地扩展...这里有2种状态:应用程序状态(或客户端状态或session)和资源状态。应用程序状态包含会话数据,并由REST客户端维护。资源状态包含资源属性和关系,并由REST服务维护。您可以很容易地确定特定变量是应用程序状态还是资源状态的一部分。如果数据量随着活动会话数的增加而增加,则它属于应用程序状态。因此,例如,当前会话的用户身份属于应用程序状态,但是用户列表或用户权限属于资源状态。

因此,REST客户端应存储标识因子,并随每个请求一起发送。不要将REST客户端与HTTP客户端混淆。它们不一样。如果REST客户端使用curl,它也可以在服务器端,或者它可以创建例如服务器端仅HTTP的cookie,它可以通过CORS与REST服务共享。唯一重要的是REST服务必须通过每个请求进行身份验证,因此您必须在每个请求中发送凭据(用户名,密码)。

  • 如果编写客户端REST客户端,则可以使用SSL + HTTP身份验证来完成。在这种情况下,您可以credentials -> (identity, permissions)在服务器上创建缓存以加快身份验证速度。请注意,如果您清除该缓存,并且用户发送相同的请求,他们将获得相同的响应,只是需要更长的时间。您可以将其与会话进行比较:如果清除会话存储,则用户将获得一个status: 401 unauthorized响应...
  • 如果编写服务器端REST客户端,并且通过curl将标识因素发送到REST服务,则有两种选择。您也可以使用http auth,也可以在REST客户端中使用会话管理器,但不能在REST服务中使用会话管理器。
  • 如果有人不信任您编写了REST客户端,则您必须编写一个应用程序来对用户进行身份验证,并为他们提供可用性,以决定他们是否要向其他客户端授予权限。Oauth是为此已经存在的解决方案。Oauth1安全性更高,oauth2安全性较低,但更简单,而且我猜想对此问题还有其他解决方案……您不必重新发明它。有使用oauth的完整身份验证和授权解决方案,例如:wso身份服务器

Cookies不一定是坏的。您可以以RESTful方式使用它们,直到它们持有客户端状态并且服务仅持有资源状态为止。例如,您可以将购物车或首选的分页设置存储在Cookie中...


1
那不是最重要的Don't worry about being "RESTful", worry about security.答案吗?
丹尼斯·布拉加2014年

为时已晚,我不知道您在说什么,对不起。:D我明天会读这篇文章,我不记得了...
inf3rno 2014年

2
我设法再次阅读了该帖子。是的,我认为这是因为与您提到的帖子相比,我的帖子延迟了2年。仅此,一个愉快的夜晚!:-)
inf3rno 2014年

只是想了解更多。第三方客户是什么意思?JWT对他们来说不安全吗?谢谢。
姚彬然后
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.