我目前正在为.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浏览器而异):
第二种方法的问题更多地集中在实现和库使用上:
每个需要验证的请求URI都必须有一个令牌参数,这是非常重要的。如果每个方法实现都需要检查令牌是否有效,那么需要编写的代码要多得多。
[RestGet("/get/{id}")]
vs. [RestGet("/get/{id}/{token}")]
.
我的想法是像http:/server/user/get/1234?token=token_id
一样将令牌作为参数传递给URL。
另一种可能是将参数作为HTTP标头发送,但我猜这会使普通HTTP客户端的使用变得复杂。
令牌将作为每个请求的自定义HTTP头("X-Session-Id")传递回客户端。
然后,这可以从接口中完全抽象出来,任何需要身份验证的实现都可以只询问令牌(如果给定)属于哪个用户。
你认为这会对REST造成太大的影响吗?或者你有更好的想法吗?
发布于 2009-01-21 20:21:39
我倾向于认为身份验证细节属于头部,而不是URI。如果您依赖于放置在URI上的令牌,那么应用程序中的每个URI都需要编码以包含该令牌。这也会对缓存产生负面影响。具有不断变化的令牌的资源将不再能够被缓存。与资源相关的信息属于URI,而不是与应用程序相关的数据,例如凭据。
看起来你一定是把网络浏览器作为客户的目标?如果是这样的话,您可以研究一下如何使用HTTP Digest access authentication或颁发客户端自己的SSL证书来唯一地标识和验证它们。另外,我不认为会话cookie一定是一件坏事。尤其是在必须处理浏览器时。只要隔离cookie处理代码,并使应用程序的其余部分不依赖它,就没有问题。关键是只在会话中存储用户的身份,而不存储其他内容。不要滥用服务器端会话状态。
如果您的目标客户不是浏览器,那么您可以采用多种方法。我有幸使用了亚马逊的S3 Authentication机制。
当然,这都是非常主观的。纯洁性和原封不动的遵循有时是不切实际的。只要最小化和隔离此类行为,应用程序的核心仍然可以是RESTful。我强烈推荐RESTful Web Services作为REST信息和方法的一个很好的来源。
发布于 2009-01-21 18:27:02
我同意workmad3的观点,如果需要维护会话生命周期,您应该创建一个会话资源。在具有用户凭据(基本身份验证或正文内容中凭据)资源上进行Post将返回唯一的会话id。在/session/{id}上删除将注销该用户。
如果您想要控制会话过期时间。当创建新会话(post on session资源)时,服务器将在响应上设置cookie (使用标准的set-cookie头)。cookie将包含过期时间。cookie字符串应在服务器上加密,因此只有服务器才能打开该cookie。对服务器的每个后续请求都将在cookie标头中发送会话cookie。(如果您的客户端是浏览器,它将自动为您完成)。服务器需要为每个请求“更新”cookie,即用新的过期时间创建新的cookie (延长会话的超时)。记住,当用户在会话资源上调用delete时,要清除cookie。
如果您希望您的应用程序更安全,您可以将客户端IP存储在cookie本身中,这样当请求到达时,服务器可以验证它是从“原始”客户端发送的。但请记住,当涉及代理时,此解决方案可能会出现问题,因为服务器可能会“看到”来自同一客户端的所有请求。
发布于 2009-01-19 18:05:38
我已经看到的rest身份验证将会话视为创建、销毁等的REST资源,然后会话ID来回传递。我见过的人倾向于使用会话cookie来实现这一点,因为这是保护它的唯一方法。如果您在URL中传递会话id,则无法真正验证它是否来自正确的客户端。
然而,身份验证是REST的一个棘手问题,因为它需要在URL之外保留某种形式的状态,这违反了URL表示状态所需的REST原则。
https://stackoverflow.com/questions/458482
复制相似问题