REST和身份validation变体

我目前正在为.net创build一个REST库,并且我想听到一些关于我有一个开放点的意见:REST和身份validation。

以下是与库一起使用的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或向需要authentication用户的请求发送令牌的主要方式。

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

  • 每次请求都会传输密码 – 即使使用SSL,也会有某种“不好的感觉”。
  • 由于密码是通过请求头传输的,因此本地攻击者很容易查看传输的头文件来获取密码。
  • 密码在浏览器内存中可用。
  • 没有标准的方法来过期用户“会话”。
  • 用浏览器login会中断页面​​的外观。

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

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

我的想法是将标记作为parameter passing给URL,如http:/server/user/get/1234?token=token_id

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

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

这可以从界面完全抽象出来,任何需要authentication的实现都可以只是询问哪个用户(如果给定的话)属于哪个用户。

你是否认为这样做会违反REST,或者你有什么更好的想法?

我倾向于认为authentication细节属于标题,而不是URI。 如果您依赖于放置在URI上的令牌,则应用程序中的每个URI都需要进行编码以包含该令牌。 这也会对caching产生负面影响。 带有不断变化的标记的资源将不再能够被caching。 与资源相关的信息属于URI,而不是与应用有关的数据,例如凭证。

看来你必须把浏览器作为客户端? 如果是这样,您可以使用HTTP摘要访问身份validation或颁发客户端自己的SSL证书进行调查,以唯一标识和validation它们。 另外,我不认为会话cookie是一件坏事。 特别是在处理浏览器时。 只要你隔离cookie处理代码,并使其他应用程序不依赖它,你会没事的。 关键只是在会话中存储用户的身份,没有别的。 不要滥用服务器端会话状态。

如果您的目标客户不是浏览器,那么您可以采取多种方法。 我已经使用亚马逊的S3身份validation机制。

这当然是非常主观的。 对信的纯度和遵守REST有时是不切实际的。 只要你最小化和隔离这样的行为,你的应用程序的核心仍然可以是RESTful。 我强烈build议将RESTful Web服务作为REST信息和方法的重要来源。

我同意workmad3,如果会话生存时间需要维护,你应该创build一个会话资源。 使用用户凭证(基本身份validation或身份内容中的凭证)发布该资源将返回唯一的会话ID。 删除/会话/ {id}会注销用户。

如果你想控制会话到期时间。 当创build新会话(在会话资源上发布)时,服务器将在响应上设置一个cookie(使用标准的set-cookie头)。 该cookie将包含到期时间。 cookiestring应该在服务器上encryption,所以只有服务器可以打开该cookie。 每个向服务器发出的请求都会在cookie头中发送会话cookie。 (如果你的客户端是浏览器,它会自动完成)。 服务器需要为每个请求“更新”cookie,即用新的到期时间(扩展会话超时)创build新的cookie。 请记得在用户调用会话资源上的删除时清除cookie。

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

我见过的其他身份validation将会话视为创build,销毁等REST资源,然后会话ID传递来回。 我见过的人倾向于使用会话cookie,因为这是确保安全的唯一方法。 如果您在URL中传递会话标识,那么您没有任何真正的身份validation方法来自正确的客户端。

对于REST来说,身份validation是一个棘手的问题,因为它需要某种forms的状态保存在URL之外,这违反了URL的REST原则,这些都是表示状态所需要的。