使用Pylons的验证和认证表单装饰器

2 投票
1 回答
713 浏览
提问于 2025-04-15 23:36

validate 和 authenticate_form 这两个装饰器似乎不太兼容。下面是我的模板:

<html>
<title>Test</title>
<body>
${h.secure_form('/meow/do_post')}
<input type="text" name="dummy">
<form:error name="dummy"><br>
<input type="submit" name="doit" value="Do It">
${h.end_form()}
</body>
</html>

这是控制器的代码:

import logging

from pylons import request, response, session, tmpl_context as c, url
from pylons.controllers.util import abort, redirect

from ocust.lib.base import BaseController, render
import formencode
import formencode.validators
from formencode import htmlfill
from pylons.decorators import validate
from pylons.decorators.secure import authenticate_form

class MeowForm(formencode.Schema):
    allow_extra_fields = True
    dummy = formencode.validators.NotEmpty()

class MeowController(BaseController):

    def index(self): 
        return render('/index.mako')

    @authenticate_form
    @validate(schema=MeowForm(), form='index')
    def do_post(self):
        return 'posted OK'

如果验证失败,@validate 装饰器会使用 htmlfill.render 重新渲染表单,但这会把身份验证令牌去掉,所以下次提交表单时就会出现 403 CSRF 检测到错误。

身份验证令牌被去掉的原因是 @authenticate_form 会从 request.POST 中删除这个令牌。

如果用这个替代:

@validate(schema=MeowForm(), form='index', force_defaults=False)

就能正常工作。那么如果把 force_defaults 设置为 False,会有什么不好的情况发生吗?htmlfill 的文档似乎建议在默认值“是表单提交的结果”时设置为 True。

1 个回答

2
@validate(schema=MeowForm(), form='index')
@authenticate_form
def do_post(self):

你需要调整一下装饰器的顺序,认证的装饰器必须放在最后面。

撰写回答