不使用重造轮子保护 REST API

在设计 REST API 时,首先对用户进行身份验证是否常见?

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

  • 用户希望得到数据。当然酷,我们喜欢分享! 获取一个公共 API 密钥和阅读!
  • 用户希望存储/更新数据... 等等! 你是谁,你可以这样做吗?

我想建立它一次,并允许说,一个网络应用程序,安卓应用程序或 iPhone 应用程序使用它。

对于这样的需求,RESTAPI 似乎是一个合乎逻辑的选择

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

我在数据库中有一个项目,它有一个 收视率属性(整数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 来说是很好的,我明白这一点。

我有很多问题,那就是如何将其与安全模型结合起来?我习惯了网络应用的安全性,在这里我有一个会话状态,可以随时识别我的用户,这样我就可以控制他们可以做什么,不管他们决定发送给我什么。据我所知,这不是 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 应用程序中使用 session,然后自己重写整个栈,对我来说,这通常意味着“你做错了”,尤其是在处理安全性问题时。

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

52734 次浏览

不要担心“休息”,担心安全性。我是这样做的:

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

步骤2: 如果凭据被签出,返回指纹、会话 ID 等。.,并将它们放入共享内存以便稍后快速检索,或者如果您不介意为 Web 服务周转时间增加几毫秒,则使用数据库。

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

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

读读这个:

RESTful 身份验证

五年后编辑

使用 OAuth2!

上一版本

不,绝对没有必要使用饼干。它的安全性还不及 HTTPDigest、 OAuth 或 Amazon 的 AWS 的一半(后者并不难复制)。

看待 cookie 的方式应该是,它与 Basic/Digest/OAuth/无论哪种方式一样,都是一种身份验证令牌,但不那么合适。

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

饼干是邪恶的,停止使用他们。

三年后编辑

我完全同意 Evert 的观点,在 HTTPS 中使用 OAuth2,不要重新发明轮子! : -)

通过简单的 REST API ——不是针对第三方客户端—— JSON Web 令牌也可以很好。

上一版本

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

不要使用会话,因为会话您的 REST 服务将无法很好地伸缩... 这里有两种状态: 应用程序状态(或客户机状态或会话 s)和资源状态。应用程序状态包含会话数据,由 REST 客户端维护。资源状态包含资源属性和关系,由 REST 服务维护。您可以非常容易地决定某个特定变量是应用程序状态的一部分还是资源状态的一部分。如果数据量随着活动会话数量的增加而增加,那么它就属于应用程序状态。例如,当前会话的用户标识属于应用程序状态,但是用户列表或用户权限属于资源状态。

因此 REST 客户机应该存储标识因子,并随每个请求一起发送。不要将 REST 客户机与 HTTP 客户机混淆。他们不一样。如果 REST 客户端使用 curl,它也可以在服务器端,或者它可以创建一个服务器端 http only 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 有完整的身份验证和授权解决方案,例如: 身份识别服务器

饼干不一定是坏东西。您可以以 RESTful 的方式使用它们,直到它们保持客户端状态,而服务只保持资源状态为止。例如,您可以在 cookies 中存储购物车或首选的分页设置..。