Disabled field is considered for validation in WTForms and Flask

后端 未结 4 777
别跟我提以往
别跟我提以往 2021-02-01 08:38

I have some fields in page disabled as for example:(using jinja2 templating system)



{{ form.na
4条回答
  •  借酒劲吻你
    2021-02-01 08:54

    This is actually an interesting problem, and the way WTForms solves it is intentionally something that requires explicitness, because it has to do with security and not allowing users to fake input.

    So the intent is, that "managers" cannot edit the name, while "admins" can.

    At first glance this seems obvious, just disable the field in HTML, and write your view like this:

    def edit_team():
        form = TeamForm(request.POST, obj=team)
        if request.POST and form.validate():
            form.populate_obj(team) # <-- This is the dangerous part here
            return redirect('/teams')
        return render('edit_team.html')
    

    As written, this is a major security risk, because the disabled property in HTML forms is client-side only. Anyone with an HTML inspector (ie FireBug, webkit document inspector, etc) can remove this property, or someone could simply make a request like so:

    POST /edit_team/7 HTTP/1.0
    Content-Type: application/x-urlencoded
    
    team=EVILTEAMNAME&title=foo
    

    The issue then is of course, how do we gate this properly on the server-side, corresponding to the appropriate way of doing this? The correct approach with WTForms is to not have the field in the first place. There's a few ways to do this, one is to use form composition and have e.g. ManagerTeamForm and AdminTeamForm (sometimes this is better) but other times it's easier to use del to remove specific fields.

    So here's how you would write your view, and not have the validation issues:

    def edit_team():
        form = TeamForm(request.POST, obj=team)
        if user.role == 'manager':
            del form.name
        if request.POST and form.validate():
            form.populate_obj(team)
            return redirect('/teams')
        return render('edit_team.html')
    

    And a quick modification to the template:

    
    
    
        {% if 'name' in form %}
            {{ form.name() }}
        {% else %}
            {{ team.name|e }}
        {% endif %}
        {{ form.title }}
        -- submit button --
    
    
    
    

    Some pieces of reference for wtforms best-practices:

    • WTForms 'Solving Specific Problems'
    • Dangers of Using forms as a backing store (WTForms google group) Post 1 / Post 2
    • StackOverflow: WTForms 'readonly' attribute

提交回复
热议问题