由于修改用户密码是在用户登录后进行的。但是当我完成这个功能后,发现密码一旦修改成功。在刷新的时候,会发现当前登录用户就变成空的了。这是由于密码修改后,原来的会话失效,可以重新到登录界面重新登录,这样可以解决这个问题,但是会影响用户体验。查阅文档,是有专门的解决方法。

这种保护只在MIDDLEWARE_CLASSESSessionAuthenticationMiddleware开启的情况下应用。如果settings.py由Django ≥ 1.7的startproject生成,它会被包含进来。

在Django 2.0中,会话验证会变成强制性的, 无论是否开启了SessionAuthenticationMiddleware 。 如果你拥有一个1.7之前的项目,或者使用不包含SessionAuthenticationMiddleware的模板生成的项目,考虑在阅读下面的升级说明之后开启它。

如果你的AUTH_USER_MODEL继承自AbstractBaseUser,或者实现了它自己的get_session_auth_hash()方法,验证后的会话会包含这个函数返回的哈希值。在AbstractBaseUser的情况中,这是密码字段的HMAC。如果开启了SessionAuthenticationMiddleware ,Django会验证每个请求带有的哈希值是否匹配服务端计算出来的哈希值。这允许用户通过修改密码来登出所有的会话。

Django中包含的默认的密码修改视图,以及django.contrib.auth中的 django.contrib.auth.views.password_change()user_change_password视图 ,会使用新的密码哈希值升级会话,以便用户在修改密码是不会登出。如果你拥有自定义的密码修改视图,并且希望具有相似的行为,使用这个函数:

update_session_auth_hash(_request_, _user_)

这个函数接受当前请求,并且会在会话哈希值得到的地方升级用户对象,也会适当地升级会话哈希值。使用示例:

from django.contrib.auth import update_session_auth_hash

def password_change(request):
    if request.method == 'POST':
        form = PasswordChangeForm(user=request.user, data=request.POST)
        if form.is_valid():
            form.save()
            update_session_auth_hash(request, form.user)
    else:
        ...

如果你在升级一个现存的站点,并且希望开启这一中间件,而不希望你的所有用户之后重新登录,你可以首先升级到DJango1.7并且运行它一段时间,以便所有会话在用户登录时自然被创建,它们包含上面描述的会话哈希。一旦你使用SessionAuthenticationMiddleware开始运行你的站点,任何没有登录并且会话使用验证哈希值升级过的用户的现有会话都会失效,并且需要重新登录。

注意

虽然get_session_auth_hash()给予SECRET_KEY,使用新的私钥升级你的站点会使所有现有会话失效。

如下,是我项目中的代码截图:

from django.contrib.auth import update_session_auth_hash

class ChangePasswordView(FormView):
    def change_password(request):
        user = request.user                         # 获取当前登录用户是哪个用户
        oldpassword = request.POST.get('a')         # 获得前端传过来的旧密码
        newpassword = request.POST.get('b')         # 获得前端传过来的新密码
        if user.check_password(oldpassword):        # 判断前端传过来的密码是否正确,如果正确,返回一个值
            user.set_password(newpassword)          # 把前端输入的新密码加密放进数据库里面
            user.save()
            update_session_auth_hash(request,user)  # 更新session,因为原来的session存放的是旧密码
            context={'a':'a'}
            return JsonResponse(context)
        else:
            context={'b':'b'}
            return JsonResponse(context)