【问题标题】:Django how to improve security of password reset?Django如何提高密码重置的安全性?
【发布时间】:2021-11-25 05:31:01
【问题描述】:

我为我的用户设置了密码重置选项。但我发现很少有安全风险:

1) 密码重置链接未过期: 现在我的密码重置链接未过期。我希望密码重置链接只能使用一次。用户不能第二次使用它来更改他的密码

2)如果用户更改HTML的值,如何防止密码更改:让你解释一下。我有一个像 <input type="hidden" name="user_id" value="{{user_id}}"> 这样的 html 隐藏输入文件,如果用户更改了 user_id 的 html 值,那么我想防止更改密码。这是我的代码:

token.py 用于发送到邮件的密码重置链接

def send_forget_password_mail(email,token):
    subject = 'EXAMPLE.COM Password Reset Link'
    message = f'hi your forgot password link http://127.0.0.1:8000/change-password/{token}'
    email_from = 'noreply@EXAMPLE.com'
    recipient_list =[email]
    send_mail(subject,message,email_from,recipient_list)
    return True

views.py

这是忘记密码视图,用户提交邮件以获取密码重置链接。在这里,我还将令牌保存在用户配置文件中。

def ForgetPassword(request):
    if request.method == "POST":
       email = request.POST["email"]
       User = get_user_model()
       if not User.objects.filter(email=email).first():
           messages.success(request, "Invalid mail")
           return redirect('members:rest-password') 
       user_obj = User.objects.get(email=email)
       print(user_obj)
       token = str(uuid.uuid4())
       profile_obj = UserProfile.objects.get(user=user_obj)
       profile_obj.forget_password_token = token
       profile_obj.save()
       send_forget_password_mail(user_obj.email,token) 
       messages.success(request, "An password reset link sent to your email")
       return redirect('members:reset-password')     
    return render(request, 'members/password_reset_form.html') 

这是用户更改密码的视图。

def ChangePassword(request,token):
    profile_obj = UserProfile.objects.filter(forget_password_token=token).first()
    User = get_user_model()
    print(profile_obj)
    if request.method == "POST":
       password1 = request.POST.get('password1')
       password2 = request.POST.get('password2')
       user_id = request.POST.get('user_id')
       if user_id is None:
           messages.success(request, "user not found")
           return redirect(f'http://127.0.0.1:8000/change-password/{token}')
       if password1 != password2:
            messages.success(request, "password didn't match")
            return redirect(f'http://127.0.0.1:8000/change-password/{token}')
       
       user_obj = User.objects.get(id =user_id)
       user_obj.set_password(password1)
       user_obj.save()
       messages.success(request, "your password sucessfully changed")
       return redirect('members:login')


    context ={'user_id':profile_obj.user.id}
    print(context)
    return render(request,'members/password_change.html',context)

【问题讨论】:

    标签: python python-3.x django


    【解决方案1】:

    对于您的第一个问题,您可以使用 Django 的设置参数PASSWORD_RESET_TIMEOUT_DAYS 来减少链接超时的天数。你可以阅读更多here。我不完全确定是否可以将其设为一次性使用链接。

    关于第二个问题,你可以用你想要的某种方式对其进行加密。

    例如,您可以添加一个模板过滤器,该过滤器将以您想要的任何方式加密您的 id。您可以让它运行凯撒加密或带有额外文本填充的异或加密,以使其更难以解密。
    类似于<input type="hidden" name="user_id" value="{{user_id|caesar}}">

    这样更改用户 ID 的可能性较小,因为在解密后如果用户 ID 不存在,您可以在提交时返回错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-22
      • 1970-01-01
      • 2013-10-17
      • 2011-01-02
      • 2019-07-26
      • 2012-01-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多