REST和身份验证变体

时间:2009-01-19 17:47:55

标签: authentication rest

我目前正在研究.net的REST库,我想听听一些关于我的开放点的看法:REST和身份验证。

以下是与库一起使用的RESTful接口的示例:

[RestRoot("/user")]
public interface IUserInterface
{
  [RestPut("/")]
  void Add(User user);

  [RestGet("/")]
  int[] List();

  [RestGet("/get/{id}")]
  User Get(int id);

  [RestDelete("/delete/{id}")]
  void Delete(int id);
}

服务器代码然后只实现接口,客户端可以通过工厂获得相同的接口。或者,如果客户端未使用该库,则标准HTTP请求也可以。

我知道有一些主要方法可以使用HTTP Basic Auth或向需要经过身份验证的用户发送令牌。

第一种方法(HTTP Basic Auth)存在以下问题(部分是Web浏览器特定的):

  • 密码随每个请求一起传输 - 即使使用SSL,也会产生某种“不良感觉”。
  • 由于密码是通过请求标头传输的,因此本地攻击者很容易查看传输的标头以获取密码。
  • 密码在浏览器内存中可用。
  • 没有标准方法可以使用户“会话”到期。
  • 使用浏览器登录会中断页面​​的外观。

第二种方法的问题更侧重于实施和图书馆使用:

  • 每个需要身份验证的请求URI都必须有令牌的参数,这只是非常重复。
  • 如果每个方法实现需要检查令牌是否有效,则需要编写更多代码。
  • 界面将变得不那么具体,例如[RestGet("/get/{id}")][RestGet("/get/{id}/{token}")]
  • 在哪里放置令牌:在URI的末尾?根之后?在其他地方?

我的想法是将令牌作为参数传递给像http:/server/user/get/1234?token=token_id这样的网址。

另一种可能性是将参数作为HTTP标头发送,但这会使普通HTTP客户端的使用变得复杂化。

令牌将作为每个请求的自定义HTTP标头(“X-Session-Id”)传递回客户端。

这可以完全从界面中抽象出来,任何需要身份验证的实现都可以询问令牌(如果给定)属于哪个用户。

你认为这会过多地违反REST,还是你有更好的想法?

3 个答案:

答案 0 :(得分:64)

我倾向于认为身份验证详细信息属于标头,而不是URI。如果您依赖于URI上的令牌,那么应用程序中的每个URI都需要进行编码以包含令牌。它还会对缓存产生负面影响。具有不断变化的令牌的资源将不再能够被缓存。资源相关信息属于URI,而不是与应用程序相关的数据,如凭证。

您似乎必须将Web浏览器定位为客户端?如果是这样,您可以使用HTTP Digest access authentication进行调查,或者向客户端发出自己的SSL证书,以便唯一地识别和验证它们。另外,我认为会话cookie不一定是坏事。特别是在不得不处理浏览器时。只要您隔离cookie处理代码并使应用程序的其余部分不依赖它,您就可以了。关键是只在会话中存储用户的身份,没有别的。不要滥用服务器端会话状态。

如果您的目标客户端不是浏览器,那么您可以采取多种方法。我很幸运使用了亚马逊的S3 Authentication机制。

这当然是非常主观的。纯粹和遵循REST的信件有时可能是不切实际的。只要您最小化并隔离此类行为,应用程序的核心仍然可以是RESTful。我强烈建议RESTful Web Services作为REST信息和方法的重要来源。

答案 1 :(得分:15)

我同意workmad3,如果需要维护会话生命周期,则应创建会话资源。使用用户凭据(基本身份验证或正文内容中的凭据)在该资源上发布将返回唯一会话ID。删除/ session / {id}将注销用户。

如果要控制会话到期时间。创建新会话(会话资源上的帖子)时,服务器将在响应上设置cookie(使用标准的set-cookie标头)。 cookie将包含到期时间。 cookie字符串应该在服务器上加密,因此只有服务器可以打开该cookie。 对服务器的每个后续请求都将在cookie头中发送会话cookie。 (如果您的客户是浏览器,它将自动为您完成)。服务器需要为每个请求“更新”cookie,即创建具有新到期时间的新cookie(延长会话超时)。 当用户在会话资源上调用delete时,请记得清除cookie。

如果您希望应用程序更安全,您可以将客户端IP存储在cookie本身中,因此当请求到达时,服务器可以验证它是从“原始”客户端发送的。但请记住,当涉及代理时,此解决方案可能会出现问题,因为服务器可能会“看到”所有请求来自同一客户端。

答案 2 :(得分:4)

我见过的其他身份验证将会话视为用于创建,销毁等的REST资源,然后会话ID来回传递。我见过的人倾向于使用会话cookie,因为这是确保它的唯一方法。如果您在URL中传递会话ID,则无法通过正确的客户端进行任何真正的身份验证。

身份验证是REST的一个棘手问题,因为它需要某种形式的状态保存在URL之外,这违反了URL的REST原则,这是表示状态所需的全部内容。