检查django表单有效性和javascript

检查django表单有效性和javascript,javascript,django,forms,validation,Javascript,Django,Forms,Validation,我使用的是django模型表单,我想保护自己不受恶意用户输入(而不仅仅是错误输入)的影响 据我所知,django表单足够安全:。是否有效()检查用户输入,csfr防止跨站点伪造 但是这次我的表单没有使用action='/path/to/my/view'调用django视图,而是使用submit按钮调用javascript函数,该函数获取数据并使用ajax调用django视图来访问数据库,然后在屏幕上显示结果 因此我认为不再需要保护(.is\u valid()未被调用,csfr未被发送)。我是对的

我使用的是django模型表单,我想保护自己不受恶意用户输入(而不仅仅是错误输入)的影响

据我所知,django表单足够安全:
。是否有效()
检查用户输入,
csfr
防止跨站点伪造

但是这次我的表单没有使用
action='/path/to/my/view'
调用django视图,而是使用submit按钮调用javascript函数,该函数获取数据并使用ajax调用django视图来访问数据库,然后在屏幕上显示结果

因此我认为不再需要保护(
.is\u valid()
未被调用,
csfr
未被发送)。我是对的?如果是这样,我该怎么办

我认为:

1) 这不是问题,表单是合理安全的(为什么?)

2) 重构代码并使用django视图

3) django表单验证都不够安全,所以无论如何我应该做更多的事情(什么?)

4) 我的javascript函数是使用ajax将数据发送到django视图。我应该使用这些数据来实例化绑定表单,并使用
。\u是否有效()
,但无论如何,我没有使用csfr,对吗

5) 使用html验证器(在我看来,它们不适合检查恶意的输入数据)

6) 其他的

一些代码,是完整的,但可能你不需要它

我的
表单.py

class NameListForm(forms.ModelForm):
    class Meta:
        model = Name
        fields = ['namelanguage', 'nametype', 'gender']
        widgets = {
            'gender': forms.CheckboxSelectMultiple(),
        }
class Name(models.Model):
    name = models.CharField(_('nome'), max_length=50, default='')
    namelanguage = models.ForeignKey(
        NameLanguage, related_name='%(app_label)s_%(class)s_language',
        verbose_name=_('linguaggio'), on_delete=models.PROTECT)
    nametype = models.ForeignKey(
        NameType, related_name='%(app_label)s_%(class)s_tipo',
        verbose_name=_('tipo'), on_delete=models.PROTECT)
    gender = models.ForeignKey(
        Gender, related_name='%(app_label)s_%(class)s_gender',
        verbose_name=_('sesso'), on_delete=models.PROTECT,
        blank=True, null=True)
def GetListName(request):
    if request.is_ajax():
        language = request.POST.get('language')
        nametype = request.POST.get('nametype')
        # it makes sense to check validity here? and anyway I'm not using csfr, right?
        # name_list_form = NameListForm({'namelanguage': language, 'nametype': nametype, etc})
        # if name_list_form.is_valid():
        ...
        return JsonResponse({'result': 'OK', 'data': my_dict})
My
models.py

class NameListForm(forms.ModelForm):
    class Meta:
        model = Name
        fields = ['namelanguage', 'nametype', 'gender']
        widgets = {
            'gender': forms.CheckboxSelectMultiple(),
        }
class Name(models.Model):
    name = models.CharField(_('nome'), max_length=50, default='')
    namelanguage = models.ForeignKey(
        NameLanguage, related_name='%(app_label)s_%(class)s_language',
        verbose_name=_('linguaggio'), on_delete=models.PROTECT)
    nametype = models.ForeignKey(
        NameType, related_name='%(app_label)s_%(class)s_tipo',
        verbose_name=_('tipo'), on_delete=models.PROTECT)
    gender = models.ForeignKey(
        Gender, related_name='%(app_label)s_%(class)s_gender',
        verbose_name=_('sesso'), on_delete=models.PROTECT,
        blank=True, null=True)
def GetListName(request):
    if request.is_ajax():
        language = request.POST.get('language')
        nametype = request.POST.get('nametype')
        # it makes sense to check validity here? and anyway I'm not using csfr, right?
        # name_list_form = NameListForm({'namelanguage': language, 'nametype': nametype, etc})
        # if name_list_form.is_valid():
        ...
        return JsonResponse({'result': 'OK', 'data': my_dict})
我的
模板.html

<form action="" method="post">
    <div>
        <div class="col-md-auto">
          {{ name_list_form.namelanguage.label_tag }}<br />
          {{ name_list_form.namelanguage }}
          {{ name_list_form.namelanguage.errors }}
        </div>
        <div class="col-md-auto">
          {{ name_list_form.nametype.label_tag }}<br />
          {{ name_list_form.nametype }}
          {{ name_list_form.nametype.errors }}
        </div>
        <div class="col-md-auto">
          {{ name_list_form.gender.label_tag }}<br />
          {{ name_list_form.gender }}<br />
          {{ name_list_form.gender.errors }}
        </div>
    </div>
    {{ name_list_form.non_field_errors }}
    <div>
        <button class="btn btn-primary" id='list_name' type="button" onclick="FilterBy()">{% trans "List Names" %}</button>
        <button class="btn btn-primary" type="button" onclick="RandomNames()">{% trans "Random Names" %}</button>
    </div>
    {% csrf_token %}
</form>
我的
视图.py

class NameListForm(forms.ModelForm):
    class Meta:
        model = Name
        fields = ['namelanguage', 'nametype', 'gender']
        widgets = {
            'gender': forms.CheckboxSelectMultiple(),
        }
class Name(models.Model):
    name = models.CharField(_('nome'), max_length=50, default='')
    namelanguage = models.ForeignKey(
        NameLanguage, related_name='%(app_label)s_%(class)s_language',
        verbose_name=_('linguaggio'), on_delete=models.PROTECT)
    nametype = models.ForeignKey(
        NameType, related_name='%(app_label)s_%(class)s_tipo',
        verbose_name=_('tipo'), on_delete=models.PROTECT)
    gender = models.ForeignKey(
        Gender, related_name='%(app_label)s_%(class)s_gender',
        verbose_name=_('sesso'), on_delete=models.PROTECT,
        blank=True, null=True)
def GetListName(request):
    if request.is_ajax():
        language = request.POST.get('language')
        nametype = request.POST.get('nametype')
        # it makes sense to check validity here? and anyway I'm not using csfr, right?
        # name_list_form = NameListForm({'namelanguage': language, 'nametype': nametype, etc})
        # if name_list_form.is_valid():
        ...
        return JsonResponse({'result': 'OK', 'data': my_dict})

CSRF和数据有效性是两个不同的主题

首先,您可以通过在请求头中发送CSRF令牌来检查CSRF错误

第二,您可以使用JS发送数据的方式与使用经典格式发送数据的方式相同

// JS, don't forget to add your CSRF headers
$.ajax({
  method: "post",
  url: "...",
  data: {
    namelanguage: "foo",
    nametype: "bar",
    gender: "baz",
  });
然后像你一样处理你的表格。如果您不确定表单是从JS脚本提交的,您可以抛出一个异常,但这并不能保证表单确实是从JS脚本提交的。任何人都可以修改客户端头,使您这样认为

# python
from django.http.response import HttpResponseBadRequest, HttpResponseNotAllowed

def GetListName(request):
    if not request.is_ajax():
        return HttpResponseNotAllowed()
    form = NameListForm(data=request.POST)
    if not form.is_valid():
        return HttpResponseBadRequest()

    # do stuff with your form
    return JsonResponse({'result': 'OK', 'data': 'some data'})

如果Post请求中未包含csrf(如果未使用csrf_豁免),django将抛出403错误。我认为,如果没有csrf令牌,您就无法向服务器发出post请求。我有一个函数可以处理每个Ajax请求。如果我理解正确,这就是我所需要的防止跨站点伪造。