欢迎来到Cecilia陈的博客

孤独,是人一生最好的修行。

20 Auth认证模块

一、Auth模块是什么

Auth模块是Django自带的用户认证模块:我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统。此时我们需要实现包括用户注册、用户登录、用户认证、注销、修改密码等功能,我们就要自己利用cookie和session去进行登录认证,这还真是个麻烦的事情呢。

Django作为一个完美主义者的终极框架,当然也会想到用户的这些痛点。它内置了强大的用户认证系统--auth,不知道大家在之前我们用django创建模型表的时候,执行数据库迁移命令和建表命令的时候,我们发现它不仅有我们自己的表,还有一些其他的表,哪些都是django中自带的表,如下图

它默认使用 auth_user 表来存储用户数据:先来看一看这张表中有哪些字段吧

二、auth模块创建超级用户

下面我们来看一张图:图中的url你是不是很熟悉啊,是我们只要创建django项目,在这个路由层中,就会默认的帮我们生成一条地址为admin的路由,不知道你有没有访问这个admin 地址去试过呢?

这里你有没有想过,这个这个用户和密码我怎么才能去创建呢,我怎么才能登录到这个真实的页面呢?下面你只要跟着我一起来做,你就会知道怎么回事了?

1.首先,先去settings里到数据库配置那里,配一个数据库,最好是配一个新的数据库
2.配置完数据库以后千万别忘了去应用名或者是跟项目名同名的文件名下的__init__文件里配置如下两条代码,因为django默认是用sqlite3数据库,所以只要我们自己配置了数据库,就一定要配置这两句
	import pymysql
	pymysql.install_as_mysql()
3.打开菜单栏tools下的tool manage.py Task界面,输入下面的代码
	createsuperuser------创建超级用户
4.看下方图解

这个时候,我们的超级用户就注册好了,我们来试一下上面的admin地址访问的效果,以及能不能用我们创建的这个用户登录上:你会惊奇的发现,登陆上去了,但是里面的内容,有些看不懂

1572511940383

这里就直接抛出概念,上图是Django专门用来管理模型表的,刚刚注册的用户,现在就可以管理django的所有模型表,只不过我们还没有创建模型表而已。

那我们在继续来看一下上面提到的,django是默认将用户认证的信息存放在auth_user表中的,来看看这张表中有什么变化:(发现多出来一条用户数据,正是我们上面个注册的超级用户,它是具有django的所有权限的)

三、Auth 自定义登录页面 登录超级用户

根据上述的超级用户的例子,我们可以利用auth模块,自己去写一个用户的登录页面,看看我们之前创建的超级用户cecilia,是否可否正常的登录。

# 首先自定义一条url

# 利用auth模块登录超级用户
url(r'^login/$',views.login),
# views.py视图函数

# 我们既然要在视图函数中用auth模块,就要先导入这个模块
from django.contrib import auth
def login(request):
    if request.method == 'POST':
        # 获取登录页面的post请求的用户名和用户密码
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 按道理来说,我们是不是应该通过表名去数据库表中查找有没有这个用户名和密码的数据
        # 但是现在这个auth_user表不是我们自己创建的模型表,所以我们没法用表名去表里查有没有这个用户数据
        # 这里就算是给了我们表名,我们就一定能够去这个表里查?
        		# 不可以,
            	# 应为auth模块在创建超级用户的时候,还记得存到表中的密码是密文的吧
                # 但是你通过表名,去查数据,查出来的是明文的,所以是不可以的
        
        # 所以我们要用auth模块去查询当前登录的用户,
        user_obj = auth.authenticate(username=username,password=password)
        # user_obj :当auth.authenicate帮我们校验数据的时候
        # 校验成功时,他是直接返回我们登录的用户名,但是是一个对象
        # 校验不成功,它就返回None
        print(user_obj)
        print(user_obj.username) # 可通过对象点的方法去值
        print(user_obj.password)
        if user_obj: # 判断是否有这个对象
            # 如果有值,则通过auth.login(request,name=user_obj),自动操作session
            auth.login(request,user_obj) # 这里是记录用户浏览器的状态
        else:
            return redirect('/login')   
            
    return render(request,'login.html')
// login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="" method="post">
    {% csrf_token %} //这里当我们不注释中间件csrf的时候,post提交数据的时候,一定要加这句话
    <p>username:<input type="text" name="username"></p>
    <p>password:<input type="text" name="password"></p>
    <p><input type="submit"></p>
</form>
</body>
</html>

现在我们来通过自己写的login页面,测试一下通过auth模块认证来做登录校验,情况如何:

  1. 首先先重启服务器,在浏览器中输入127.0.0.1:8001/login,进入登录页面后,登录我们之前通过命令注册的超级用户

  1. 在来看看我们在服务器通过打印auth模块拿到的返回值,得到的是什么结果
user_obj = auth.authenticate(username=username,password=password)
        # user_obj :当auth.authenicate帮我们校验数据的时候
        # 校验成功时,他是直接返回我们登录的用户名,但是是一个对象
        # 校验不成功,它就返回None
        print(user_obj)
        print(user_obj.username)  # 可通过对象点的方法去值
        print(user_obj.password)

  1. 在继续访问输入127.0.0.1:8001/login,进入登录页面,f12打开开发者工具,看看auth模块自动帮我们做的session设置,在看服务器上默认保存session的那张名为django_session的表中,有没有在服务端保存的session值
auth.login(request,user_obj)

四、auth模块 常用方法

4.1 如何创建超级用户

超级用户就是用于登录django admin的后台管理

# 其实如何去创建超级用户,在上面已经有了
1. 打开tools manage.py Task终端窗口
	createsuperuser
2. 根据提示,去输入用户名,密码就好了(附图)    

4.2 如何使用普通的登录页面校验用户存不存在

auth模块的功能就是我们不用自己通过cookie和session去记录用户浏览器的登录状态了

现在比如我就以上面我创建好的超级用户,去写一个普通的登录页面,我去做一个登录校验,看看能不能登录成功

# 首先默认我们已经写好了一个登录页面,现在去输入用户的用户名和密码:(默认是正确的)
# 然后利用auth模块帮我们校验这个超级用户存不存在

# 这就是在校验我输入的密码,和超级用户的密码是否匹配
user_obj = auth.authenticate(username=username,password=password)

注意:当user_obj 存在的时候返回的是一个以用户名为名的对象,可以做如下操作;当校验失败的时候,user_obj==None

user_obj.usernmae
user_obj.password
·····

4.3 auth 保存用户登录状态

在我们学auth模块之前,我们是自己通过cookie和session的方法,自己在服务端写保存用户登录状态的

现在 auth模块帮我们做了这件事情,所以有了一句话,要用auth模块就用全套的,不要一部分自己写,一部分用auth

auth.login(request,user_obj)
# 在用户登录成功以后,执行这一句操作,我们会发现,在浏览器和服务端,都出现当前浏览器的session

最重要的是:只要我们执行完上面一句话之后,只要是能拿到request的地方,我们都可以通过request.user获取到当前登录的用户对象

4.4 auth 的request.user

request.user
# 当用户登录的情况下,返回的结果是用户对象
# 当用户没有登录的情况下,返回的一个AnonymoUser---匿名用户

# 但是当我们如果需要对当前用户有没有登录,进行一些逻辑处理的时候,很明显,当用户没有登录的情况下,我们通过request.user不好进行判断呀

request.user.is_authenticated() 
# 如果用户登录:返回True
# 用户没有登录:返回False

4.5 局部配置/全局配置 装饰器

那如果我又多个视图,我想要在每一个视图函数都校验一下,用户有没有登录,没有登录就回到的登录页面,如果的登录了,就回到我们访问的页面

那现在,是不是可以想到装饰器啊,那这里,装饰器也不需要我们自己写了,用auth的,步骤如下

from django.contrib.auth.decorators import login_required
# 局部配置,就是只对当前被装饰的有效
# 用我们以前用过的装饰器的方法,来装饰需要被装饰的视图函数
@login_requirde ## 仅仅这样是不行的,如过直接这样的话,我们用的就是auth默认的装饰器了


# 所以必须要这样写
@login_required(login_url = '/login') # 配置成我们自己的url路径
# 全局配置:在settings中配置,因为如果我们有一百个视图函数都需要用到装饰器的时候,			用局部配置的,也会出现代码的冗余现象,因为我们毕竟要写100行

# 在settings中配置如下代码
LOGIN_URL = '/login/'

# 然后我们的装饰器就可以这样写
@login_required

4.6 利用装饰器实现用户密码修改

如果我现在想要修改当前用户的密码,而修改密码,我是不是正常情况下来看,修改密码应该在用户登录的情况下才能去做把,

我们继续用上面注册好的超级用户来测试

# views.py


# 用户登录功能
def login(request):
    next_page = request.GET.get('next')
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        user_obj = auth.authenticate(username=username,password=password)
        if user_obj:
            auth.login(request, user_obj)
            if next_page:
                return redirect(next_page)
            else:
                return redirect('/login')
        return HttpResponse('用户名密码错误!')
    return render(request,'login.html')


# 修改密码
from django.contrib.auth.decorators import login_required
@login_required(login_url='/login/')
def set_pwd(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        old_pwd  =request.POST.get('old_pwd')
        new_pwd  =request.POST.get('new_pwd')
        
        # 拿到用户输入的旧密码后,通过auth模块,
        # check_password()方法,检验这个用户的密码和它输入的旧密码一致不一致
        is_right = request.user.check_password(old_pwd)
        if is_right:# 如果一致
            # 通过request.user拿到当前登录的用户对象
            # 通过set_password()方法将原密码改为用户设置的新密码
            request.user.set_password(new_pwd)

            # 写完上面的那一步还没有完,必须要写下面这句,保存到数据表中
            request.user.save()
            return redirect('/login')
    return render(request,'set_pwd.html')


# 首页
from django.contrib.auth.decorators import login_required
@login_required(login_url='/login/')
def home(request):
    return HttpResponse('我是首页')

4.7 auth 如何注册新的用户

from django.contrib.auth.models import User

User.objects.create_user(username=username,password=password)  # 创建普通用户
# 此处如果直接使用crete的话,会将密码存成明文的,下次就登录不上了
       User.objects.create_superuser(username=username,password=password,email='123@qq.com') # 创建超级用户  邮箱字段必须填写

五、扩展 auth_user 表的字段

扩展 auth_user 表的字段有两种方式:

第一种(不推荐使用):利用一对一的表关系来创建,扩展字段

第二种(通过继承):通过继承原来 auth_user的类,

这里我们主要讲述第二种方法

思想:
 1. 首先我们在应用的模型层中导入
     from django.contrib.auth.models import AbstractUser
        
 2. 自己定义一个类继承(AbstractUser)
	注意:你继承了AbstractUser之后 你自定义的表中 字段不能跟原有的字段冲突
    
 3.一定要在settings配置文件中指定
    AUTH_USER_MODEL = 'app01.Userinfo'
    # 固定语法: AUTH_USER_MODEL = '应用名.表名'    

注意:当我们需要在auth_user表中扩充新的字段的时候,一定一定要确保,当前的应用中不能有任何的迁移记录,因为只要有迁移记录,就代表你已经把auth_user表迁移过来了,这个模型表就已经实例化了

posted @ 2019-10-31 22:44  Cecilia陈  阅读(303)  评论(0编辑  收藏  举报