Django框架(十一):用户认证组件

文章目录

  • 一、auth模块
    • 1、先看下 auth_user表
    • 2、auth模块用法
        • (1)authenticate()---用户名、密码验证
        • (2)login(HttpRequest, user)---用户登录
            • 【1】login用法及底层的session实现
            • 【2】AuthenticationMiddleware中间件源码分析
        • (3)logout(request)---用户注销(退出登录)
    • 3、user对象
        • (1)创建用户---用户注册
            • 【1】创建普通用户
            • 【2】创建超级用户
        • (2)用户修改密码
            • 【1】check_password()---验证原来密码
            • 【2】 set_password()---修改密码
        • (3)判断当前用户是否登录两种方法
            • 【1】is_authenticated()
            • 【2】login_required装饰器
        • (4)用户对象的属性
  • 二、扩展默认的auth_user表

我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统。此时我们需要实现包括 用户注册、用户登录、用户认证、注销、修改密码等功能,这还真是个麻烦的事情呢。

Django作为一个完美主义者的终极框架,当然也会想到用户的这些痛点。它内置了强大的用户认证系统–auth,它默认使用 auth_user 表来存储用户信息

注意:这个用户认证组件的底层是基于session实现的,session又要借助cookie实现!因此学习时,尽量想想底层的session实现!可以结合上篇博文学习:Django框架(十):Cookie与Session

一、auth模块

1、先看下 auth_user表

python3.7 manage.py makemigrations
python3.7 manage.py migrate
python3.7 manage.py createsuperuser # 创建超级用户

Django框架(十一):用户认证组件_第1张图片Django框架(十一):用户认证组件_第2张图片通过上图我们可以清晰看到auth_user的字段,还有特别注意这个密码是采用了sha256加密算法加密过了!

因此不能像一般取数据库中的数据,密码是密文的
Django框架(十一):用户认证组件_第3张图片注意User拿到的是个model,当然也不能通过User.objects.create(username="admin",password="admin")这样来创建用户!我们马上会讲专门的语法来创建普通用户、超级用户,不会使用python3.7 manage.py这种,更不能使用create这种!

2、auth模块用法

from django.contrib import auth

auth中提供了许多实用方法,如下!

(1)authenticate()—用户名、密码验证

提供了用户认证,即验证用户名以及密码是否正确,一般需要username password两个关键字参数
如果用户名、密码正确,会返回一个 User 对象,否则返回的就是一个None对象。authenticate()会在User 对象上设置一个属性标识那种认证后端认证了该用户,且该信息在后面的登录过程中是需要的。
当我们试图登陆一个从数据库中直接取出来不经过authenticate()的User对象会报错的!!
Django框架(十一):用户认证组件_第4张图片authenticate的底层session实现
Django框架(十一):用户认证组件_第5张图片

(2)login(HttpRequest, user)—用户登录

【1】login用法及底层的session实现

该函数接受一个HttpRequest对象,以及一个认证了的User对象
此函数使用django的session框架给某个已认证的用户附加上session id等信息。
Django框架(十一):用户认证组件_第6张图片login的底层session实现
Django框架(十一):用户认证组件_第7张图片request.user里面存的是用户信息字典,后面我们就可以通过request.user.get('username')获取用户的用户名等信息!

注意:
只要使用login(request, user_obj)之后,request.user就能拿到当前登录的用户对象。否则request.user得到的是一个匿名用户对象(AnonymousUser Object)。
详细原理请查看 AuthenticationMiddleware 中间件源码。

【2】AuthenticationMiddleware中间件源码分析

AuthenticationMiddleware这是一个用户认证的中间件!request.user刚才我们说了在login中被赋值,这个是正确的,但有很多小伙伴可能会认为,request.user的生成就在这里,其实不然!request.user最早的生成是在AuthenticationMiddleware中间件里!

接下来带大家分析一下这个中间件的源码:
Django框架(十一):用户认证组件_第8张图片

Django框架(十一):用户认证组件_第9张图片从这里我们就可以看出来request.user=get_user(request),也就是说在这个时候,我们已经可以确认用户登录状态了!如果未登录的,这里的request.user就等于一个匿名对象,已登录的用户,就会把当前用户信息作为字典赋值给request.user。后面走视图函数啊,啥的,request.user拿到的都是当前用户的信息数据了!


注意:从这里开始下面所有中间件源码分析,仅个人想法,可能会有错误,仅供参考!


只要login之后你的登录状态,用户信息数据都会被保存至django-session表中,那么你进网站的时候拿着sessionid去查是否有这个session-key,有就是一个已登录的用户,没带着sessionid、或session-id不存在,那么就是未登录的,返回匿名对象!未登录的我们应该让他进入登录界面,未登录的才需要登录(login),当前request.user为匿名对象,login之后应该是已登录用户,我们需要将原来的request.user为匿名对象重新赋值为一个user对象,这件事login也帮我们做了,但我们要理解!

问题来了,既然最开始中间件哪里我们有一次request.user=user了,为什么login这里还需要呢?

确实,其实login不用做request.user=user也是可以的
login的request.user=user,应该只是方便你本次访问中使用request.user获取用户信息数据,看下图

Django框架(十一):用户认证组件_第10张图片如果我们在auth.login后面还需要利用request.user做些事情,那么就必须request.user = user,不然你当前是匿名对象,无法做事情!登录之后,下一次访问该网站任何页面,request.user就是在中间件处就又执行了一次request.user = user!因此如果你auth.login后面只是重定向到首页,那么login的request.user = user这个操作可有可无!

(3)logout(request)—用户注销(退出登录)

该函数接受一个HttpRequest对象,无返回值。当调用该函数时,当前请求的session信息会全部清除。该用户即使没有登录,使用该函数也不会报错。

    # 1:request.COOKIE.get("sessionid)   #取cookie中的值
    # 2:在Django - session表过滤session - key的记录并与删除这条记录
    # 3:删除cookie,response.delete_cookie("sessionid")
session:
    request.session.flush()   # 相当于上面3个步骤

  '''
auth模块:
    auth.logout(request)  # 相当于上面的那个flush步骤
    '''

3、user对象

(1)创建用户—用户注册

【1】创建普通用户

create_user()

from django.contrib.auth.models import User # 导入User模型
user = User.objects.create_user(username='',password='',email=''
【2】创建超级用户

create_superuser()

from django.contrib.auth.models import User
user_obj = User.objects.create_superuser(username='用户名',password='密码',email='邮箱',...

(2)用户修改密码

【1】check_password()—验证原来密码

auth 提供的一个检查密码是否正确的方法,需要提供当前请求用户的密码。

密码正确返回True,否则返回False。

ok = user_obj.check_password('密码')

用户修改密码,这个功能肯定是登录后才能修改嘛,登录后的密码修改,填入原密码,这里check_password,成功即可set_password()修改密码

没登录就说明忘记了密码需要修改密码,此时这个功能应该在登录界面,忘记密码三种处理方法方法

  • 手机号发验证码,核对验证码,然后执行下面的修改密码
  • 手机换号了,那就只剩下申诉了!申诉成功再执行下面的修改密码
  • 最近很多用户规模比较大的app,推出了人脸识别+绑定的原手机号来找回密码!
【2】 set_password()—修改密码

auth 提供的一个修改密码的方法,接收 要设置的新密码 作为参数。

注意:设置完一定要调用用户对象的save方法!!!

# user_obj并不只能通过create_user拿到,request.user这也是一个user_obj
user_obj.set_password('新密码')
user_obj.save()

(3)判断当前用户是否登录两种方法

【1】is_authenticated()

如果是真正的 User 对象,返回值恒为 True 。 用于检查用户是否已经通过了认证。
通过认证并不意味着用户拥有任何权限,甚至也不检查该用户是否处于激活状态,这只是表明用户成功的通过了认证。 这个方法很重要, 在后台用request.user.is_authenticated()判断用户是否已经登录,如果true则可以向前台展示request.user.name

要求:

1. 用户登陆后才能访问某些页面,
2. 如果用户没有登录就访问该页面的话直接跳到登录页面
3. 用户在跳转的登陆界面中完成登陆后,自动访问跳转到之前访问的地址

# 上面三种要求(场景)都要求每个页面必须判断当前请求页面的用户是否登录了!

因此我们可以用下面代码完成对用户是否登录的判断:

def my_view(request):
  if not request.user.is_authenticated():
    return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))

这个settings.LOGIN_URL大家可能不知道是什么,看下面的装饰器就知道了!当然你也可以指定跳转到其他url!不一定非要LOGIN_URL,但一般都是跳转到LOGIN_URL

【2】login_required装饰器

如果我们使用request.user.is_authenticated,那么每个页面的视图函数里你都要写这么一句话:

if not request.user.is_authenticated():
  return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))

这样是不是很麻烦!因此django已经为我们设计好了一个用于此种情况的装饰器:login_requierd()

from django.contrib.auth.decorators import login_required
       
@login_required
def my_view(request):
  ...

加上这个装饰器,有两个作用:

  • 若用户没有登录,则会跳转到django默认的 登录URL '/accounts/login/ ’
    (这个值可以在settings文件中通过LOGIN_URL进行修改)。
  • 假如我访问了首页,我没有登录,那么会跳转到LOGIN_URL,并且会记录跳转到LOGIN_URL之前的访问url的绝对路径 ,登陆成功后,会重定向到该路径。

(4)用户对象的属性

# user_obj并不只能通过create_user拿到,request.user这也是一个user_obj
user_obj能够拿到认证所用用户表的数据属性,比如username, password等。

其他特殊常用属性含义如下:

is_staff : 用户是否拥有网站的管理权限.

is_active : 是否允许用户登录, 设置为 False,可以在不删除用户的前提下禁止用户登录。

详细参数如下:
Django框架(十一):用户认证组件_第11张图片

二、扩展默认的auth_user表

你可能感兴趣的:(#,框架,django)