保护REST API而不重新发明轮子

在deviseREST API时,通常先validation用户身份?

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

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

我想build立一次,并允许说一个networking应用程序,一个Android应用程序或iPhone应用程序来使用它。

REST API似乎是这样的需求的合理select

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

我有一个数据库中的项目,它有一个评级属性(整数1到5)。

如果我正确理解REST,我将使用我select的语言来实现GET请求,该语言返回如下所示的csv,xml或json:

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

说我们select我们返回的JSON:

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

这对于面向公众的API来说很好。 我得到那部分。

我有很多问题是如何将这与安全模型相结合? 我习惯了networking应用程序的安全性,我有一个会话状态在任何时候都可以识别我的用户,所以我可以控制他们可以做什么,不pipe他们决定发送给我什么。 据我所知,这不是RESTful,所以在这种情况下将是一个不好的解决scheme。

我会尝试使用相同的项目/评级的另一个例子。

如果用户“JOE”想要添加评级到一个项目

这可以使用:

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

在这一点上,我想存储的数据说,“JOE”给了产品{id}评级{givenRating}。

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

此外,如果是用户的电话号码更合理的数据呢?

我到目前为止是:

1)使用HTTP的内置function在每个请求进行身份validation,无论是纯HTTP还是HTTPS。

这意味着每个请求现在都采取以下forms:

 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以及。

5年后编辑

使用OAuth2!

以前的版本

不,绝对不需要使用cookie。 它不如HTTP摘要,OAuth或Amazon的AWS(这不难复制)安全一半。

您应该查看Cookie的方式是,这是一个身份validation令牌,与Basic / Digest / OAuth /以较高者为准,但不太合适。

不过,只要会话cookie的内容不影响从服务器返回的资源的内容,我并不认为使用cookie 本身违背RESTful原则。

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

不要担心“RESTful”,担心安全。 以下是我如何做到这一点:

第1步:用户使用凭据访问身份validation服务。

第2步:如果凭证签出,返回一个指纹,会话ID等…,并将其popup到共享内存中以便稍后快速检索,或者如果您不介意在Web服务周转时间内添加几毫秒。

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

步骤4:如果指纹和会话ID无效或超时redirect到authentication。

读这个:

RESTfulauthentication

3年后编辑

我完全同意Evert,使用HTTPS使用OAuth2 ,不要重新发明轮子! 🙂

通过更简单的REST API(不适用于第三方客户端), JSON Web Tokens也可以。

以前的版本

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

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

因此,REST客户端应该存储识别因素并将其发送给每个请求。 不要将REST客户端与HTTP客户端混淆。 他们不一样。 REST客户端也可以在服务器端,如果它使用curl,或者它可以创build例如服务器端http only cookie,它可以通过CORS与REST服务共享。 REST服务必须通过每个请求进行身份validation,因此必须在每个请求中都发送凭据(用户名,密码)。

  • 如果您编写客户端REST客户端,则可以使用SSL + HTTP身份validation完成此操作。 在这种情况下,您可以在服务器上创buildcredentials -> (identity, permissions)caching,以便更快地进行身份validation。 请注意,如果清除该caching,并且用户发送相同的请求,则它们将得到相同的响应,只是需要更长的时间。 您可以将其与会话进行比较:如果您清除会话存储,那么用户将得到一个status: 401 unauthorized响应…
  • 如果您编写服务器端REST客户端,并通过curl将标识因子发送到REST服务,则您有2个select。 您也可以使用httpauthentication,也可以在REST客户端中使用会话pipe理器,但不能在REST服务中使用。
  • 如果有人不信任地写入你的REST客户端,那么你必须编写一个应用程序来validation用户,并给他们提供可用性,以决定他们是否要将权限授予不同的客户端。 Oauth是一个已经存在的解决scheme。 Oauth1更安全,oauth2不太安全,但更简单,我想这个问题还有其他几个解决scheme…你不必重新创build这个。 有完整的身份validation和授权解决scheme使用oauth,例如: 身份validation服务器 。

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