一起学习Django框架(十一)Auth组件

目录


简介:

在平常我们使用Django开发的过程中都需要设计web的用户系统其中包含:用户注册、登录、修改密码、登录认证、注销等功能。而这些全部都是由我们手动将数据拿到数据库表中进行一一配对,太过于麻烦,那么我们今天使用到的Auth组件可以完美解决这个问题,提升使用Django的开发效率。


一、Auth组件是什么

Auth是Django自带的用户认证组件

Django作为一个完美主义者的终极框架,当然也会想到开发者的这些痛点。它内置了强大的用户认证系统:auth,它默认使用auth_user表来存储用户数据(也就是第一次迁移时Django创建的表之一)


二、Auth组件常用方法

我们可以通过以下来导入Auth组件:

from django.contrib import auth

2.1 create_user() 创建用户

auth 提供的一个创建新用户的方法,需要提供必要参数(username、password)等。

导入方式:

from django.contrib.auth.models import User

我们创建的用户默认会被添加到auth_user表中,首先我们得有一个注册页面,便于能够快速起到效果,这里就没有校验二次密码了,有兴趣的可以自己添加。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>register</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
    <div class="row">
        <h1 class="text-center">用户注册</h1>
        <form action="" method="post">
            {% csrf_token %}
            <p>用户名:<input type="text" name="username" class="form-control"></p>
            <p>密码:<input type="password" name="password" class="form-control"></p>
            <p><input type="submit" value="注册提交" class="form-control btn-warning"></p>
        </form>
    </div>
</div>
</body>
</html>

视图

from django.contrib.auth.models import User

def auth_register(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('username')

        User.objects.create_user(username=username, password=password)

        return HttpResponse('注册成功!!!')

    return render(request, 'register.html')

那么此时我们就实现了用户的账号注册功能。在auth_user表中就可以看到我们刚才注册的用户,并且Django帮助我们存储的过程中将密码进行了加密处理。

一起学习Django框架(十一)Auth组件



2.2 authenticate() 用户认证

提供了用户认证功能,即验证用户名以及密码是否正确,一般需要username 、password两个关键字参数。

导入方式:

from django.contrib.auth import authenticate

如果认证成功(用户名和密码正确有效),便会返回一个 User 对象。

authenticate()会在该 User 对象上设置一个属性来标识后端已经认证了该用户,且该信息在后续的登录过程中是需要的。

登录web

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>register</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
    <div class="row">
        <h1 class="text-center">用户登录</h1>
        <form action="" method="post">
            {% csrf_token %}
            <p>用户名:<input type="text" name="username" class="form-control"></p>
            <p>密码:<input type="password" name="password" class="form-control"></p>
            <p><input type="submit" value="登录" class="form-control btn-warning"></p>
        </form>
    </div>
</div>
</body>
</html>

视图

def auth_login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')

        user = authenticate(username=username, password=password)
        # 账号或者密码不正确:返回None,账号或者密码正确:返回User对象

        if user:  # 判断是否登录成功
            return HttpResponse('登录成功!')
        else:
            return HttpResponse('账号或者密码错误')
    return render(request, 'login.html')

此时,我们便已经完成验证用户账号和密码是否正确的一个功能,此时再浏览器输入正确的用户名与密码就会显示登录成功!

究其本质还是Django把我们输入的内容拿到了auth_user表中对比,配对成功了返回一个User对象给我们,只不过这些步骤我们只需要调用一个API就可以实现。



2.3 login(HttpRequest, user) 登录状态保持

如果现在有一个Home页面需要登录之后才能访问,那么我们就需要在用户登录之后制作一个登录标识保存在Session中,那么访问Home页面校验一下Session即可判断出来。这是我们之前的操作,需要手动设置Session,在手动校验Session是否存在。

login函数接受一个HttpRequest对象,以及一个经过认证的User对象。

该函数实现一个用户登录的功能。它本质上会在后端为该用户生成相关session数据。

该函数需要在用户认证以后使用,因为它的第二个参数需要传入一个User对象

from django.contrib.auth import authenticate,login

def auth_login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')

        user = authenticate(username=username, password=password)
        # 账号或者密码不正确:返回None,账号或者密码正确:返回User对象

        if user:  # 判断是否登录成功
            login(request,user) # 保持用户相关Session,这样用户就可以访问登录后才能访问的页面
            return HttpResponse('登录成功!')
        else:
            return HttpResponse('账号或者密码错误')
    return render(request, 'login.html')

别急,我们需要配合下面的Auth方法一起使用才能看到效果



2.4 is_authenticated 登录认证判断

用来判断当前请求是否通过了登录认证。其主要还是判断请求内是否包含用户登录后的Session

定义一个Home页面,只有检测到用户登录后才能访问,否则重定向到登录页面

def auth_home(request):
    if request.user.is_authenticated: # 判断当前请求是否为登录状态
        return render(request,'home.html')
    return redirect('/login/')

ps:request.user具备很多方法,一些其它的常用方法在有需求的过程中再了解

request.user.username:查看当前登录的用户名
request.user.password:查看当前登录的用户密码(加密形式的)

到这里我们已经实现了登录认证,登录状态保持的一个效果,后端也可以识别当前是否为登录状态,并且知道当前登录的用户是哪个。



2.5 logout(request) 退出登录

该函数接受一个HttpRequest对象,无返回值。

当调用该函数时,当前请求的Session信息会全部清除。即使没有登录,使用该函数也不会报错。

后端清空了当前用户保存的Session信息,也可以理解为没有登录状态了,下次访问某些页面需要重新登录

from django.contrib.auth import authenticate,login,logout

def auth_logout(request):
    logout(request)
    return HttpResponse('已注销登录')


2.6 login_requierd() 登录认证装饰器

在上面我们是通过以下代码校验是否登录的

def auth_home(request):
    if request.user.is_authenticated: # 判断当前请求是否为登录状态
        return render(request,'home.html')
    return redirect('/login/')

为了更加简单实现,auth 给我们提供的一个装饰器工具,用来快捷的给某个视图添加登录校验

@login_required
def auth_home(request):
    return render(request,'home.html')

若用户没有登录,则会跳转到Django默认的登录URL /accounts/login/ 并且URL会额外显示:?next=/跳转之前的路径/

如果需要自定义登录的URL,有两种方式:

  1. 需要在settings.py文件中通过LOGIN_URL进行修改。

    LOGIN_URL = '/login/'  # 这里配置成你项目登录页面的路由
    
  2. 手动指定:用户没有登录时重定向到登录页面

    @login_required(login_url='/login/')
    def auth_home(request):
        return render(request,'home.html')
    

如果我们想要在登录之后立马跳转到被重定向之前的页面,使用方式一,因为它会保留重定义之前的URL:

if user:
    login(request,user) # 保持用户相关Session,这样用户就可以访问登录后才能访问的页面
    urls = request.GET.get('next') # 获取重定向之前的页面url
    if not urls:
        urls = '/index/' # 如果没有获取到,就默认登录后跳转到首页
    return redirect(urls)


2.7 check_password(password) 检查密码

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

密码正确返回True,否则返回False。但必须在登录之后并且保存了登录Session才能使用

使用方式:

user = request.user.check_password('密码')


2.8 set_password(password) 设置密码

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

注意:设置完一定要调用用户对象的save方法!!!通常在check_password校验之后使用

我们使用这两个来实现修改密码的功能

web:modify.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>register</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
    <div class="row">
        <h1 class="text-center">修改密码</h1>
        <form action="" method="post">
            {% csrf_token %}
            <p>旧密码:<input type="text" name="old_password" class="form-control"></p>
            <p>新密码:<input type="password" name="new_password" class="form-control"></p>
            <p><input type="submit" value="提交" class="form-control btn-warning"></p>
        </form>
    </div>
</div>
</body>
</html>

视图

@login_required
def auth_modify(request):
    if request.method == 'POST':
        user = request.user # 获取当前用户对象
        old_password = request.POST.get('old_password')

        if request.user.check_password(old_password): # 判断用户输入的密码是否正确
            new_password = request.POST.get('new_password') # 获取用户输入的新密码
            user.set_password(new_password)
            user.save() # 将修改后的数据保存到auth_user表中

            login(request,user) # 因为用户信息发生变动,需要修改用户的Session数据才能保持登录状态

            return HttpResponse('密码修改成功!!!')

        return HttpResponse('原密码输入错误!!!')

    return render(request,'modify.html')


2.9 用户删除

如果是管理员的话,可以删除其它用户。如果是普通用户的话,只能删除自己

管理员删除需要前端传递一个用户id到后端才能进行删除;需要路由定义分组来接收并传递给视图函数

@login_required
def auth_delete(request,pk):
    logout(request)
    user = User.objects.filter(pk=pk)
    user.delete()

    return HttpResponse('...')

路由:

path('del-<int:pk>/',views.auth_delete),

普通用户,删除自身。

@login_required
def auth_delete(request):
    request.user.delete()

    return HttpResponse('...')

注意:如果连接的是sqlite数据库,很可能会删除失败(笔者已经经历两次了),建立换成MySQL数据库



2.10 创建超级用户

超级用户首先具备登录admin后端的能力,其次可以在里面删除其它用户;

超级用户的创建方式有两种:

  1. 通过:Python3 manage.py createsuperuser命令,根据提示输入用户名、邮箱(可输入空)、密码、二次密码等
  2. 通过Auth组件创建;与创建普通用户区别不大,只是获得权限不同

web:register2.html 建立超级用户

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>register</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
    <div class="row">
        <h1 class="text-center">超级用户创建</h1>
        <form action="" method="post">
            {% csrf_token %}
            <p>用户名:<input type="text" name="username" class="form-control"></p>
            <p>邮箱:<input type="email" name="email" class="form-control"></p>
            <p>密码:<input type="password" name="password" class="form-control"></p>
            <p><input type="submit" value="提交" class="form-control btn-warning"></p>
        </form>
    </div>
</div>
</body>
</html>

视图

def auth_create_superuser(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        email = request.POST.get('email')
        password = request.POST.get('username')

        User.objects.create_superuser(username=username,email=email,password=password)

        return HttpResponse('超级用户创建成功!!!')

    return render(request, 'register2.html')

创建完成以后我们就可以通过刚刚创建的账号和密码登录到Django的admin后台管理界面了

一起学习Django框架(十一)Auth组件



三、拓展auth_user表

虽说Django提供给我们的内置用户认证系统很好,但是固定字段就那么几个,并不能实际应用啊。

如果我们还需要给用户增加一个存储手机号的字段,那么此时我们就需要对auth_user表进行扩写了。

我们可以通过继承内置的 AbstractUser 类,来定义一个自己的Model类,这样既能根据项目需求灵活的设计用户表,又能使用Django强大的认证系统了。

注意:如果auth_user表已经存在了,那么我们只能新建一个库来创建表了。必须在Django的一些默认表还未创建之前完成我们下面的操作

模型:models.py

from django.contrib.auth.models import AbstractUser

class UserInfo(AbstractUser):
    phone = models.CharField(max_length=20)
    addr = models.CharField(max_length=60)

按上面的方式扩展了内置的auth_user表之后,一定要在settings.py中告诉Django,我现在使用新定义的UserInfo表来做用户认证。写法如下:

AUTH_USER_MODEL = "app01.UserInfo"
# AUTH_USER_MODEL = "app名称.表名"

不仅表名替换成了我们模型的名称,而且额外增加了我们扩写的字段,效果如下:

一起学习Django框架(十一)Auth组件


如果本文对您有帮助,别忘一键3连,您的支持就是笔者最大的鼓励,感谢阅读!


技术小白记录学习过程,有错误或不解的地方请指出,如果这篇文章对你有所帮助请点赞 收藏+关注 子夜期待您的关注,谢谢支持!

上一篇:AWS EC2 实例IP问题调研


下一篇:Go + gRPC-Gateway(V2) 构建微服务实战系列,小程序登录鉴权服务(三):RSA(RS512) 签名 JWT(附demo)