CherryPy REST身份验证

CherryPy REST身份验证,rest,authentication,cherrypy,Rest,Authentication,Cherrypy,我对Python和CherryPy非常陌生,并尝试构建一个基本的web应用程序,该应用程序将使用restfulapi从服务器查询数据。我正试图从一开始就用正确的方式去做。我还没有弄清楚的一个部分是API的身份验证,因为REST应该是无状态的,并且您不使用会话 我希望能够将我的API用于没有cookie的“本机客户端”,因此使用会话cookie不是一个选项。数据将通过HTML格式的AJAX访问。OAuth似乎是一个选项,但我不想依赖第三方提供登录服务(Facebook在几周前几乎离线了一天) 有人

我对Python和CherryPy非常陌生,并尝试构建一个基本的web应用程序,该应用程序将使用restfulapi从服务器查询数据。我正试图从一开始就用正确的方式去做。我还没有弄清楚的一个部分是API的身份验证,因为REST应该是无状态的,并且您不使用会话

我希望能够将我的API用于没有cookie的“本机客户端”,因此使用会话cookie不是一个选项。数据将通过HTML格式的AJAX访问。OAuth似乎是一个选项,但我不想依赖第三方提供登录服务(Facebook在几周前几乎离线了一天)

有人能给我指出正确的方向吗?这对CherryPy是有用的。

对于RESTful身份验证,没有“正确的方法”。REST本身并不是API的银弹。您需要权衡对it的需求和解决方案及其优缺点。不过,我将介绍在CherryPy开箱即用的HTTP标准方法

您在评论中链接的文章非常清楚以无状态方式进行身份验证的简单方法——HTTPS。还有一个,它本身不传输密码并防止重播攻击,所以在普通HTTP上使用它是可以的

#!/usr/bin/env python
# -*- coding: utf-8 -*-


import cherrypy


userpassdict  = {'user1': 'passwd'}
checkpassword = cherrypy.lib.auth_basic.checkpassword_dict(userpassdict)
get_ha1       = cherrypy.lib.auth_digest.get_ha1_dict_plain(userpassdict)

config = {
  'global' : {
    'server.socket_host' : '127.0.0.1',
    'server.socket_port' : 8080,
    'server.thread_pool' : 8
  },
  '/' : {
    # HTTP verb dispatcher
    'request.dispatch': cherrypy.dispatch.MethodDispatcher(),
    # JSON response
    'tools.json_out.on' : True,
    # Basic Auth
    'tools.auth_basic.on'            : True,
    'tools.auth_basic.realm'         : 'Walled garden',
    'tools.auth_basic.checkpassword' : checkpassword,
    # Digest Auth
    #'tools.auth_digest.on'      : True,
    #'tools.auth_digest.realm'   : 'Walled garden',
    #'tools.auth_digest.get_ha1' : get_ha1,
    #'tools.auth_digest.key'     : 'put random secret here',
  }
}


class Document:
  '''Test like:
  curl --user user1:passwd --request GET http://localhost:8080/api/document
  curl --user user1:passwd --request GET http://localhost:8080/api/document/2
  curl --user user1:passwd --request POST --data name="new entry" http://localhost:8080/api/document
  curl --user user1:passwd --request PUT --data name="new entry2" http://localhost:8080/api/document/4
  curl --user user1:passwd --request DELETE http://localhost:8080/api/document/4
  '''

  _store  = None
  exposed = True


  def __init__(self):
    self._store = {
      1 : {'id': 1, 'name': 'foo'},
      2 : {'id': 2, 'name': 'bar'},
      3 : {'id': 3, 'name': 'baz'},
      4 : {'id': 4, 'name': 'qux'},
    }

  def GET(self, id = None):
    if id:
      return self._store[int(id)]
    else:
      return self._store.values()

  def POST(self, **kwargs):
    id = max(self._store.keys()) + 1
    self._store[id] = {'id': id, 'name': kwargs['name']}
    return id    

  def PUT(self, id, **kwargs):
    self._store[int(id)].update(kwargs)

  def DELETE(self, id):
    self._store.pop(int(id))


if __name__ == '__main__':
  cherrypy.quickstart(Document(), '/api/document', config)

OAuth似乎是一个什么选项?一旦您进行了授权,您仍然必须以某种方式将会话保存在cookie中,或者通过更改连接状态来保存会话。基本上你说的是“我想让服务器知道我是被授权的,而不知道这一点”。我建议改变你的假设,让那些“本地客户机”支持cookie(或同等产品)。否则,我怀疑你能做什么。@奇怪的饼干不应该和其他东西一起使用,它们会变得有状态。REST应该通过令牌进行身份验证,而不必在服务器上存储任何状态或会话数据。看看,伙计,饼干和代币在概念上没有区别。这只是一个词。此外,您会将该令牌存储在客户端的何处?如果您说客户端不支持cookies。并且连接不会因为cookies而变得有状态。客户端/用户代理是无状态的,而API/服务器是无状态的。REST要求仅适用于服务器。基本前提是,要么服务器记住谁登录(在请求之间),这在服务器上是状态完整的,要么客户端必须发送一些东西(cookie/HTTP auth/token/signature)在每个请求上对自己进行身份验证,在这种情况下,服务器需要在每个请求上检查这一点。