CherryPy自定义工具用于用户认证

3 投票
2 回答
7114 浏览
提问于 2025-04-16 20:40

我正在尝试在我的CherryPy控制器类中设置一个简单的方法装饰器,这样如果用户还没有登录,就会被重定向到登录页面。我本来打算用一个基本的Python装饰器,但这里的一个回答建议我使用CherryPy自定义工具。所以我在尝试这样做,但我无法让它工作。以下是我目前的代码:

def authenticate():
    user = cherrypy.session.get('user', None)
    if not user:
        raise cherrypy.HTTPRedirect('/?errMsg=Please%20log%20in%20first')

cherrypy.tools.authenticate = cherrypy.Tool('on_start_resource', authenticate)

/home页面是一个应该限制给已认证用户访问的页面,所以我写了这个:

@cherrypy.expose
@cherrypy.tools.authenticate
def home(self, **kwargs):
    tmpl = TemplateDir.get_template('home.mako')
    return tmpl.render()

但是,当我尝试启动我的网站时,出现了这个错误:

Traceback (most recent call last):
  File ".\example.py", line 3, in <module>
    from controller.main import Root
  File "C:\...\controller\main.py", line 9, in <module>
    class Root(BaseModule):
  File "C:\...\controller\main.py", line 19, in Root
    @cherrypy.tools.authenticate
  File "C:\Python26\lib\site-packages\cherrypy\_cptools.py", line 119, in
   __call__ % self._name)
TypeError: The 'authenticate' Tool does not accept positional arguments; you must
  use keyword arguments.

编辑:好的,如果我在使用自定义工具时加上括号,我会得到一个不同的错误。

@cherrypy.expose
@cherrypy.tools.authenticate() # Magic parentheses...
def home(self, **kwargs):
    ...

现在我得到的是:

Traceback (most recent call last):
  File "C:\Python26\lib\site-packages\cherrypy\_cprequest.py", line 625, in respond
    self.hooks.run('on_start_resource')
  File "C:\Python26\lib\site-packages\cherrypy\_cprequest.py", line 97, in run
    hook()
  File "C:\Python26\lib\site-packages\cherrypy\_cprequest.py", line 57, in __call__
    return self.callback(**self.kwargs)
  File ".\example.py", line 40, in authenticate
    user = cherrypy.session.get('user', None)
AttributeError: 'module' object has no attribute 'session'

编辑:我已经开启了会话功能:

cherrypy.tools.sessions.storage_type = 'file'
cherrypy.tools.sessions.storage_path = r'%s\sessions' % curDir
cherrypy.tools.sessions.timeout = 60
cherrypy.tree.mount(Root(), "/", config={
    '/static': {
        'tools.staticdir.on':True,
        'tools.staticdir.dir':r'%s\static' % curDir,
    },
    '/': {
        'tools.sessions.on':True,
    }
})

当我第一次加载带有自定义工具装饰器的网页方法时,我遇到了这个错误:

AttributeError: 'module' object has no attribute 'session'

然后当我重新加载页面时,我又遇到了这个错误:

AttributeError: '_Serving' object has no attribute 'session'

编辑:即使在我的控制器类中尝试了这么多,我仍然得到“模块对象没有属性session”的错误:

class Root(BaseModule):
    _cp_config = {'tools.sessions.on': True}
    sess = cherrypy.session # Error here
    ...

2 个回答

0

很可能是会话功能没有开启。你可以在这个会话的维基页面上找到一个示例配置文件,或者看看第七个教程

5

我之前用错了钩子。把:

cherrypy.tools.authenticate = cherrypy.Tool('on_start_resource', authenticate)

改成:

cherrypy.tools.authenticate = cherrypy.Tool('before_handler', authenticate)

就解决了问题。显然,我的 authenticate 方法在会话还没开启的时候就被调用了,所以它无法访问 cherrypy.session。我在控制器里不需要任何开启会话的东西;只需要在我的服务器启动脚本里加上以下内容:

def authenticate():
    ...
cherrypy.tools.authenticate = cherrypy.Tool('before_handler', authenticate)
cherrypy.tree.mount(Root(), "/", config={
    "/": {
        'tools.sessions.on':True,
        'tools.sessions.storage_type':'file',
        'tools.sessions.storage_path':r'%s\sessions' % curDir,
        'tools.sessions.timeout':60
    }, ...
})

然后,在我的控制器中对一个受限的方法:

@cherrypy.expose
@cherrypy.tools.authenticate()
def home(self, **kwargs):
    ...

撰写回答