简体   繁体   English

仅在回答了安全性问题之后,才将用户保存在数据库上(使用ModelForm)?

[英]Save user on database (using ModelForm), only after security questions has been answered?

I am trying to develop a website,where in the signup flow after entering the user credentials and successfully validating Google reCaptcha, the user has to be directed to a page, displaying a list of security questions,the user has to answer one of the question to successfully signup on the website. 我正在尝试开发一个网站,在输入用户凭据并成功验证Google reCaptcha后的注册流程中,必须将用户定向到页面,显示安全问题列表,用户必须回答其中一个问题在网站上成功注册。

My forms.py file is here. 我的forms.py文件在这里。

import re
from django import forms 
from django.contrib.auth.forms import AuthenticationForm, PasswordResetForm, SetPasswordForm
from .models import CustomUser
from django.conf import settings
from django.utils.translation import ugettext as _
import urllib
import urllib.request as urllib2
import json

class SignUpForm(forms.ModelForm):
    """
    A form that creates a user, with no privileges, from the given username and
    password.
    """
    password1=  forms.CharField(label='Password',widget=forms.PasswordInput)
    password2=forms.CharField(label='Confirm Password', widget=forms.PasswordInput)

class Meta:
    #model to be used
    model = CustomUser

    #fields that have to be populated
    fields=['username']


def __init__(self,*args,**kwargs):
    self.request=kwargs.pop('requestObject',None)
    super(SignUpForm,self).__init__(*args,**kwargs)
    self.fields['username'].required=True
    self.fields['password1'].required=True
    self.fields['password2'].required=True


def clean(self):
    super(SignUpForm,self).clean()

    '''
    Test the Google Recaptcha
    '''
    #url at which request will be sent
    url='https://www.google.com/recaptcha/api/siteverify'

    #dictionary of values to be sent for validation
    values={
         'secret': settings.GOOGLE_RECAPTCHA_SECRET_KEY,
        'response': self.request.POST.get(u'g-recaptcha-response', None),
        'remoteip': self.request.META.get("REMOTE_ADDR", None),
    }

    #making request
    data=urlllib.parse.urlencode(values)
    binary_data=data.encode('utf-8')
    req= urllib.request.Request(url, binary_data)
    response= urllib.request.urlopen(req)
    result = json.loads(response.read().decode('utf-8'))

    # result["success"] will be True on a success
    if not result["success"]:
        raise forms.ValidationError("Only humans are allowed to submit this form.")

        return self.cleaned_data

def clean_password2(self):
    #checking whether the passwords match or not
    password1=self.cleaned_data.get('password1');
    password2=self.cleaned_data.get('password2');

    if password1 and password2 and password1!=password2:
        raise forms.ValidationError("Passwords don't match!");

    return password2;

def save(self, commit=True):
    #overriding the default save method for ModelForm
    user = super(UserCreationForm, self).save(commit=False)
    user.set_password(self.cleaned_data["password1"])
    if commit:
        user.save()
    return user

The models.py file is here models.py文件在这里

 from django.db import models
 from django.conf import settings
 from django.contrib.auth.models import AbstractUser

# Create your models here. 

#Choices of questions
SECRET_QUESTION_CHOICES = (
        ('WCPM', "In which city did your parents meet?"),
        ('WCN', "What was your childhood nickname?"),
        ('WPN', "What is your pet's name?"),
)


#Secret Questions
class SecretQuestion(models.Model):
    id=models.AutoField(primary_key=True)
    secret_question = models.CharField(max_length = 100, choices =     SECRET_QUESTION_CHOICES, default = SECRET_QUESTION_CHOICES[0],null=False, blank=False)

class Meta:
    db_table='Security Questions'


class CustomUser(AbstractUser):
    profile_pic = models.ImageField(upload_to = 'profile_pics/', blank = True, null = True)
    following = models.ManyToManyField('self', symmetrical = False, related_name = 'followers', blank = True)
    ques_followed = models.ManyToManyField('question.Question', related_name = 'questions_followed', blank = True)
    topic_followed = models.ManyToManyField('topic.Topic', related_name = 'topic_followed', blank = True)
    security_questions = models.ManyToManyField(SecretQuestion, related_name = 'secret_question_user', through = "SecretQuestionAnswer")

    class Meta:
        db_table = 'User'  

    def __str__(self):
        return self.username

class SecretQuestionAnswer(models.Model):
    user = models.ForeignKey(CustomUser)
    secret_question = models.ForeignKey(SecretQuestion)
    answer = models.CharField(max_length = 100,blank=False, null=False)

    class Meta:
        db_table='SecretQuestionAnswer'    

Now, after successfully submitting the SignUpForm, the user should only be registered(means saved on the database) if he answers one of the questions given above successfully. 现在,在成功提交SignUpForm之后,仅当用户成功回答上述问题之一时,才应该注册该用户(意味着该用户已保存在数据库中)。 How should work on this problem? 应该如何解决这个问题? Please help. 请帮忙。

I have been banging my head on this problem for the past two days. 在过去的两天里,我一直在努力解决这个问题。

Can somebody help. 有人可以帮忙吗?

Normaly you need to have a boolean field which will indicate if the user was finished will all steps. 通常,您需要具有一个布尔字段,该字段将指示用户是否完成所有步骤。 By default this field will be False , and when ready set it to True . 默认情况下,此字段为False ,准备好后将其设置为True You can allow login only when field is set to True . 仅当field设置为True时,才可以允许登录。

Another approach is using a wizard http://django-formtools.readthedocs.org/en/latest/ . 另一种方法是使用向导http://django-formtools.readthedocs.org/en/latest/ With this approach you need to protect user's password somehow because it's not a good idea to stay in the session. 使用这种方法,您需要以某种方式保护用户的密码,因为留在会话中不是一个好主意。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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