Restful Web服务authentication
我有一个Restful Web服务API,由不同的第三方使用。 该API的一部分受到限制(您需要用户名/密码才能访问)。 我想知道什么是实现身份validation的最佳方式?
我正在使用https,因此通信被encryption。 我有两个想法:
- 在用户开始使用(受限)服务之前,它使用POST发送用户名/密码(因为正在使用https来encryption凭据)。 login成功后,服务器发回与此用户名匹配的随机一次性使用值(nonce)。 当下一个请求正在进行时,客户端发送先前返回的现时。 服务器匹配用户名和随机数,并沿请求的数据返回新的随机数。 每个新请求使用新的随机数。 基本上,这是一个Digest访问authentication的轻量级版本。
- 由于此API是从第三方使用的,所以用户名/密码可以用于每个(受限制的)请求。 由于正在使用https,它们将被encryption。 这种方法的崩溃是这样的事实,这不会是兼容的(POST将始终使用)。
我更接近于select第一种方法(这是Restful兼容,相对容易实现,XML,JSON或HTML可以使用而不用改变任何东西),但我想看看你的意见? 你有什么build议:第一,第二或第三种方法?
顺便说一句,我在服务器端使用Python。
我在API中看到的一种方式(以及目前正在实现的方式)是创build一个名为Session的RESTful资源,它是通过提供用户名和密码的POST创build的。
这里基本上是我如何实现它:
POST /sessions { Username: "User", Password: "Password" }
创build一个有时间限制的会话并返回包含会话密钥值和到期时间的会话资源。 您可能还想将其作为cookie值返回,以方便实现API客户端。
DELETE /session/{id}
立即使会话过期,不能再使用。 这用于显式注销。
然后我有用户通过查询参数附加会话密钥,虽然你也可以允许它通过cookie值提交,我build议允许这两个。
我更喜欢这个,它非常简单。
很明显,你的场景会决定你的会话应该如何pipe理,也许它们不是时间限制和持续时间的限制,为了增加安全性,也许它们被散列或encryption。
如果你在任何地方使用HTTPS,你可能不需要太担心。 但是,如果您想使用HTTP,则需要使用类似散列的密码以及密钥,并说明一个时间戳,以便为每个请求生成一个安全密钥。 这样,您可以通过HTTPS共享密钥,然后切换到HTTP进一步调用。 即使有人设法从请求中嗅出密钥,它几乎可以立即过期而无用。
免责声明:我不是安全专家;-)。
没有理由不在这里使用HTTPauthentication。
也就是说,发布时间块nonce的概念可以很好地工作。 但是这是为什么你首先需要跳过这个额外的箍环的动机。
当使用bcrypt散列作为原始密码时,这个技术被考虑到了,因为validation用户的实际花费(如果你不知道,bcrypt可以被调整到大量的实时执行散列函数)。 做出这样的select是为了让服务“login”一次,使用通过bcrypt经过昂贵的validation过程的密码,然后得到一个时间阻塞的令牌,以换取将绕过bcrypt过程的未来请求。
在bcrypt进程的情况下,使用HTTP身份validation,该服务既可以使用正常密码,也可以使用令牌。 这样用户可以随时使用密码进行他们的服务,但只是变得昂贵。 所以他们可以做到这一点,他们只是不应该。 该服务不关心客户端使用哪种authentication技术。
随机提供的nonce服务可以提高吞吐量。
除此之外,这是标准的HTTP身份validation,但有一个新的scheme。
亚马逊的networking服务做得很好,查看一些想法的方法。 从本质上讲,他们可以让客户使用他们的密码encryption一个特殊的http头。
这是链接:
http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html
假设服务在浏览器中不被使用,并且通信被encryption,我认为在第二种方法的变体中没有任何坏处:添加X-Headers来发送每个请求的用户名/密码,例如:
GET /foo HTTP/1.1 Host: www.bar.com X-MyUsername: foo X-MyPassword: bar
另一个想法是使用HTTP基本身份validation,并发送一个Authorization: Basic base64(user:password)
页眉。 也就是说,如果连接总是被encryption的话。