用户注册、用户登录、用户认证、注销、修改密码
等功能,这还真是个麻烦的事情呢。
Django作为一个完美主义者的终极框架,当然也会想到用户的这些痛点。它内置了强大的用户认证系统–auth,它默认使用 auth_user 表来存储用户信息
。
注意:这个用户认证组件的底层是基于session实现的,session又要借助cookie实现
!因此学习时,尽量想想底层的session实现!可以结合上篇博文学习:Django框架(十):Cookie与Session
python3.7 manage.py makemigrations
python3.7 manage.py migrate
python3.7 manage.py createsuperuser # 创建超级用户
通过上图我们可以清晰看到auth_user的字段,还有特别注意这个密码是采用了sha256加密算法加密过了!
因此不能像一般取数据库中的数据,密码是密文的
注意User拿到的是个model,当然也不能通过User.objects.create(username="admin",password="admin")这样来创建用户
!我们马上会讲专门的语法来创建普通用户、超级用户,不会使用python3.7 manage.py这种,更不能使用create这种!
from django.contrib import auth
auth中提供了许多实用方法,如下!
提供了用户认证,即验证用户名以及密码是否正确,一般需要username password两个关键字参数
如果用户名、密码正确,会返回一个 User 对象,否则返回的就是一个None对象
。authenticate()会在User 对象上设置一个属性标识那种认证后端认证了该用户,且该信息在后面的登录过程中是需要的。
当我们试图登陆一个从数据库中直接取出来不经过authenticate()的User对象会报错的!!
authenticate的底层session实现
:
该函数接受一个HttpRequest对象,以及一个认证了的User对象
此函数使用django的session框架给某个已认证的用户附加上session id等信息。
login的底层session实现
:
request.user里面存的是用户信息字典,后面我们就可以通过request.user.get('username')
获取用户的用户名等信息!
注意:
只要使用login(request, user_obj)之后,request.user就能拿到当前登录的用户对象
。否则request.user得到的是一个匿名用户对象(AnonymousUser Object)。
详细原理请查看 AuthenticationMiddleware 中间件源码。
AuthenticationMiddleware这是一个用户认证的中间件!request.user刚才我们说了在login中被赋值,这个是正确的,但有很多小伙伴可能会认为,request.user的生成就在这里,其实不然!request.user最早的生成是在AuthenticationMiddleware中间件里!
从这里我们就可以看出来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获取用户信息数据,看下图
如果我们在auth.login后面还需要利用request.user做些事情,那么就必须request.user = user
,不然你当前是匿名对象,无法做事情!登录之后,下一次访问该网站任何页面,request.user就是在中间件处就又执行了一次request.user = user!因此如果你auth.login后面只是重定向到首页,那么login的request.user = user这个操作可有可无!
该函数接受一个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步骤
'''
create_user()
from django.contrib.auth.models import User # 导入User模型
user = User.objects.create_user(username='',password='',email='')
create_superuser()
from django.contrib.auth.models import User
user_obj = User.objects.create_superuser(username='用户名',password='密码',email='邮箱',...)
auth 提供的一个检查密码是否正确的方法,需要提供当前请求用户的密码。
密码正确返回True,否则返回False。
ok = user_obj.check_password('密码')
用户修改密码,这个功能肯定是登录后才能修改嘛,登录后的密码修改,填入原密码,这里check_password,成功即可set_password()修改密码
!
没登录就说明忘记了密码需要修改密码,此时这个功能应该在登录界面,忘记密码三种处理方法方法
:
auth 提供的一个修改密码的方法,接收 要设置的新密码 作为参数。
注意:设置完一定要调用用户对象的save方法!!!
# user_obj并不只能通过create_user拿到,request.user这也是一个user_obj
user_obj.set_password('新密码')
user_obj.save()
如果是真正的 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
如果我们使用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):
...
加上这个装饰器,有两个作用:
值可以在settings文件中通过LOGIN_URL进行修改
)。并且会记录跳转到LOGIN_URL之前的访问url的绝对路径 ,登陆成功后,会重定向到该路径。
# user_obj并不只能通过create_user拿到,request.user这也是一个user_obj
user_obj能够拿到认证所用用户表的数据属性,比如username, password等。
其他特殊常用属性含义如下:
is_staff : 用户是否拥有网站的管理权限.
is_active : 是否允许用户登录, 设置为 False,可以在不删除用户的前提下禁止用户登录。