简体   繁体   中英

UserCreationForm Django

I'm trying to create a sign-up form, but I notice that when I render {{ form.as_p }} with a UserCreationForm, all possible fields appear for the user. Now some of the fields, I want only accessible to admins.

So, I know that you can specify the fields in the Meta Class through fields=(f1,f2...)

But wouldn't a malicious user still be able to manually submit a POST request with the 'secret' fields even though they aren't technically displayed in the form?

The only way I know how to combat this is to manually validate each field and to construct the model objects myself to ensure that the user does not touch these 'secret' fields. How, this seems to defeat the purpose of using a UserCreationForm. Is there a better way about this?

For reference, when I mean defeating the purpose for a UserCreationField, I wouldn't be able to use user = super(UserCreationForm,self).save(commit=True) safely?

If the form doesn't know the field exists (ie, it is not in the fields list of its meta class), then it won't look for a value for it in the submitted data. Hence you are perfectly safe saving the data from the form.

As an example, suppose we have the following model:

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=100)
    age = models.PositiveIntegerField(blank=True, null=True)
    hobbies = models.CharField(max_length=200, blank=True, null=True)

We can then write a LimitedCreateForm which only gets the name and hobbies and doesn't set the age. For test purposes, we can then use this form in a view which dumps the submitted data and the corresponding created person back to the browser for debugging purposes:

from django.shortcuts import render
from django import forms

from testapp.models import Person

class LimitedCreateForm(forms.ModelForm):
    class Meta:
        model = Person
        fields = ('name', 'hobbies')

def create_limited(request):
    submitted = ""
    new_user = None

    if request.method == 'POST':
        submitted = str(request.POST)
        form = LimitedCreateForm(request.POST)
        if form.is_valid():
            new_user = form.save()

    else:
        form = LimitedCreateForm()

    data = {
        'form': form,
        'submitted': submitted,
        'new_user': new_user,
    }

    return render(request, 'create_limited.html', data)

The final step in the test is to create a template which displays the debugging data (the POST data from the form and the corresponding person created), and creates a 'malicious' form with a field for the age in it:

<html>

<body>

<h1>
Submitted data:
</h1>

<p>
{{ submitted|default:"Nothing submitted" }}
</p>

<h1>
Created user
</h1>

<p>
Name: {{ new_user.name|default:"Nothing" }}
<br />
Age: {{ new_user.age|default:"Nothing" }}
<br />
Hobbies: {{ new_user.hobbies|default:"Nothing" }}
</p>

<h1>
Form
</h1>

<form method="post">
    {% csrf_token %}
    Name: <input type="text" name="name" id="id_name">
    <br />
    Age: <input type="text" name="age" id="id_age">
    <br />
    Hobbies: <input type="text" name="hobbies" id="id_hobbies">
    <br />
    <input type="submit" value="Create" />
</form>

</body>

</html>

If we then run it, and submit some values, we get the following debugging output:

Submitted data:

<QueryDict: 
{u'age': [u'27'], 
u'csrfmiddlewaretoken': [u'ed576dd024e98b4c1f99d29c64052c15'], 
u'name': [u'Bruce'], 
u'hobbies': [u'Dancing through fields of flowers']}>`

Created user

Name: Bruce 
Age: Nothing 
Hobbies: Dancing through fields of flowers

This shows the form ignored the submitted age of 27, and only saved the fields it was told about.

It is worth noting that this is also the case if you specify a list of fields to exclude (ie, exclude = ('age',) rather than fields = ('name', 'hobbies') in the forms meta class).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM