首页 文章

REST和身份验证变体

提问于
浏览
68

我目前正在为.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,它也有某种"bad feeling" .

  • 由于密码是使用请求标头传输的,因此本地攻击者很容易查看传输的标头以获取密码 .

  • 密码在浏览器内存中可用 .

  • 没有标准方法使用户"sessions"到期 .

  • 使用浏览器登录会中断页面的外观 .

第二种方法的问题更侧重于实现和库使用:

  • 每个需要身份验证的请求URI都必须具有令牌的参数,这只是非常重复 .

  • 如果每个方法实现需要检查令牌是否有效,则需要编写更多代码 .

  • 界面将变得不那么具体,例如 [RestGet("/get/{id}")][RestGet("/get/{id}/{token}")] .

  • 在哪里放置令牌:在URI的末尾?根之后?别的地方?


我的想法是将令牌作为参数传递给URL,如 http:/server/user/get/1234?token=token_id .

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

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

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

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

3 回答

  • 63

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

    您似乎必须将Web浏览器定位为客户端?如果是这样,您可以调查使用HTTP Digest access authentication或向客户端发出自己的SSL证书来唯一标识和验证它们 . 另外,我在会话中没有't think that session cookies are necessarily a bad thing. Especially when having to deal with a browser. As long as you isolate the cookie handling code and make the rest of the application not rely on it you would be fine. The key is only store the user'的身份,没有别的 . 不要滥用服务器端会话状态 .

    如果您的目标客户端不是浏览器,那么您可以采取多种方法 . 我've had luck with using Amazon' s S3 Authentication机制 .

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

  • 4

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

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

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

  • 15

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

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

相关问题