python - 更新密码但无法从 django 中的更新密码登录
问题描述
更新用户密码首先从 URL 获取用户名并更新密码。
不确定此代码是否有效,因为我无法再次使用旧密码登录,即使使用更新的密码也是如此。
视图.py:
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponse
from django.contrib.auth import authenticate, login
from django.contrib.auth.models import User
from django.contrib import auth
def change_password2(request, user_username):
var_username = get_object_or_404(User, username=user_username)
#getting username from url
u = User.objects.get(username__exact=var_username)
password = request.POST.get('password_update', False)
u.set_password(password)
b = u.save()
update_session_auth_hash(request, b)
messages.success(request, 'Your password was successfully updated!')
# return redirect('change_password')
return render(request, 'accounts/change_password2.html')
更改密码2.html:
<form method="POST" action="/account/password2/">
{% csrf_token %}
<input type="password" name="password_update">
<input type="submit" name="">
</form>
url.py
from django.urls import path
from .import views
urlpatterns = [
path('', views.account, name='account'),
path('account/', views.account, name='account'),
path('signup/', views.signup, name='signup'),
path('password2/<slug:user_username>/', views.change_password2, name='change_password2'),
]
尝试隐身但由于缓存而不确定。
解决方案
这里:
u = User.objects.get(username__exact=var_username)
# ...
b = u.save()
update_session_auth_hash(request, b)
Model.save()
返回None
(提示:作为一般规则,在 Python 中,在原地更改对象的方法通常返回None
),因此您将传递None
给update_session_auth_hash()
. 你想要这个:
u = User.objects.get(username__exact=var_username)
u.set_password(the_new_password_here)
u.save()
update_session_auth_hash(request, u)
我不知道这是否是阻止您的代码(某种)工作的唯一原因,但这是一个明显的障碍。
现在正如我所提到的,您的代码是一团糟并且存在巨大的安全漏洞-实际上它允许任何人将其他任何人的密码更改为任何...您说这只是为了练习,但我建议您花时间阅读contrib.auth
源代码以了解如何安全地做到这一点。
wrt/混乱部分:
# First point: 'user_username' is redundant to say the least,
# and since usernames can be changed you should use the user.id
# instead - or actually not use anything, cf below
#
# Second point: your view should be restricted to authenticated
# users only (using the `login_required` decorator being the
# simple and obvious way)
#
# Third point: only the admins and the (authenticated) user himself
# should be allowed to change the user's password. Since admins
# already can do this in the (django) admin, here you actually want
# to only allow the current authenticated user to change his own
# password, so you shouldn't pass the user id nor username and
# only work on `request.user`
#
# Fourth point: this view should either test on the request
# method and only performs updates on a POST request, or
# just plain refuse any other method than POST (there's
# a decorator for this too). Remember that GET requests
# **MUST** be idempotent.
def change_password2(request, user_username):
# this returns the User matching `user_username`
var_username = get_object_or_404(User, username=user_username)
# this does the exact same thing AGAIN (so it's totally useless)
# and actually only works by accident - you're passing the user
# object as argument where a username (string) is expected,
# and it only works because the string representation of a
# User is the username and the ORM lookup will force
# the argument to string.
u = User.objects.get(username__exact=var_username)
# Here you accept just anything as password, and
# if you don't have one you'll try to use `False`
# instead, which is probably not what you want.
#
# You should actually use a Django form to validate
# you inputs...
password = request.POST.get('password_update', False)
u.set_password(password)
ETC...
推荐阅读
- jmeter - Jmeter form_key 显示 form_key=deleted
- php - 发布文件 url 有退格时出错
- java - 从速度模板中的 Hashmap 中按键获取特定值
- javascript - 如何将日期从 2018-04-29 格式转换为 29 Apr,2018 格式?
- javascript - d3.js 上的双面树
- javascript - 通过js键码允许带有数值的点/句号
- ios - ViewModel 函数:无法赋值:'error' 是 'let' 常量
- python - 引用和打印字典中的值 (Python)
- spring - 如何将 JWT 令牌用于 Spring Boot 安全性
- c# - Nethereum C# 自动以太传输