Django之Auth认证组件

一、Auth是什么?

Auth模块是django自带的用户认证模块。

它内置了强大的用户认证系统——auth(from django.contrib import auth)

它默认使用auth_user表来存储用户数据

 二、走近Auth(常用方法)

authenticate()

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

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

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

用法:

  • user = authenticate(username='usernamer',password='password')

login(HttpRequest, user)

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

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

下面通过一个登录的函数来试试

 auth模块默认用auth_user表来存储用户数据:

命令行创建一个超级用户(在Tools里的run manage.py Task):createsuperuser

可以看到,默认的密码是加密的。

写一个登录的视图函数:

def auth_login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        '''之前我们要先查,然后比对,现在试试auth模块的authenticate()方法
        models.User.objects.filter(username=username,password=password).first()'''
        user_obj = auth.authenticate(request, username=username, password=password)
        if user_obj:
            '''记录用户状态,之前我们用的是request.session["name"] = "shj"'''
            auth.login(request, user_obj)  # 一旦登录了,可以在任何地方,通过request.user获取到当前登录的对象
            return HttpResponse('ok')
    return render(request, 'auth_login.html')

 is_authenticated()

用来判断当前请求是否通过了认证。

def auth_index(request):
    print(request.user.is_authenticated())  # 判断当前用户是否已经登录
    print(request.user, type(request.user))
    # AnonymousUser <class 'django.utils.functional.SimpleLazyObject'>
    # 没有登录时,显示我是游客身份
    # 登录后就是我注册的admin
    return HttpResponse('ok')

logout(request) 

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

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

def auth_logout(request):
    auth.logout(request)  # 相当于request.session.flush()
    return HttpResponse('ok')

 

User对象:

 from django.contrib.auth.models import User

User实质上是默认的用户表。

User对象属性:username, password

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

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

  • User.objects.create(username=username,password=password)  # 不能再用create创建,它创建的密码是明文的
  • User.objects.create_user(username=username,password=password)  # 创建普通用户
  • User.objects.create_superuser(username=username,password=password,email='123@163.com')  # 创建超级用户

创建超级用户需要一个email字段是必填的。

下面来写一个注册示例

def auth_register(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 只需通过用户名查询用户是否已存在(如果是自己建的表),如果是默认的表,用户名和密码都得传
        user_obj = auth.authenticate(request, username=username)
        if user_obj:
            return HttpResponse('当前用户已存在')
        User.objects.create_user(username=username, password=password)
    return render(request, 'auth_register.html')

auth_register.html

<form action="" method="post">
    {% csrf_token %}
    <p>username:<input type="text" name="username"></p>
    <p>password:<input type="password" name="password"></p>
    <input type="submit">
</form>

从表中看到,注册成功后,因为我用的是创建普通用户,所以is_superuser字段为0,自然也没有网站管理权限,因此is_staff也为0,没有登录过,所以last_login为空。后面的date_joined时间为UTC标准时间,比中国时间慢8H。 

 check_password(password)

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

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

set_password(password)

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

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

写一个修改密码的示例

def set_password(request):
    user = request.user
    err_msg = ''
    if request.method == 'POST':
        old_password = request.POST.get('old_password', '')
        new_password = request.POST.get('new_password', '')
        repeat_password = request.POST.get('repeat_password', '')
        # 检查旧密码是否正确
        if user.check_password(old_password):  
            if not new_password:
                err_msg = '新密码不能为空'
            elif new_password != repeat_password:
                err_msg = '两次密码不一致'
            else:
                user.set_password(new_password)  # 设置新密码
                user.save()  # 修改完后一定要保存,否则更改就无效了
                return redirect("/login/")
        else:
            err_msg = '原密码输入错误'
    content = {
        'err_msg': err_msg,
    }
    return render(request, 'set_password.html', content)

 

login_requierd()

auth 给我们提供的一个装饰器工具,用来快捷的给某个视图添加登录校验。

from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import login_required
@login_required
def auth_home(request):
    return HttpResponse('我是home页面,登录才能访问')
@login_required
def auth_xxx(request):
    return HttpResponse('我是xxx页面,登录才能访问')

若用户没有登录,则会跳转到django默认的 登录URL '/accounts/login/ ' 并传递当前访问url的绝对路径 (登陆成功后,会重定向到该路径)。

如果是自定义的url,那么直接访问auth_home和auth_xxx会报错。

要解决这个问题,有两种方式

  1. 局部配置:@login_required(login_url='/auth_login/')——即在装饰器指定跳转的login的路径
  2. 到配置文件进行全局配置

通过上面也可以看到,如果我们访问的页面需要登录,那么在跳转到登录页面时,会在路径后拼接我原来要访问的路径

那么后续可以通过request.GET.get('next')可以拿到原来的路径,然后等登录成功后,我们可以通过代码重定向到用户本来要访问的网页。

三、AbstractUser扩展默认的auth_user表

 内置的认证系统虽然好用,但是auth_user表字段都是固定的那几个,我在项目中没法拿来直接使用啊!

别着急!人家当然考虑到这点了!

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

 首先得到配置文件修改默认的表:

# 告诉django不再使用默认的auth_user,而使用我们自己定义的表
# AUTH_USER_MODEL = "app名.models里面对应的模型表名"
AUTH_USER_MODEL = 'app01.Userinfo'

然后建表,并执行数据库迁移命令:

from django.db import models
from django.contrib.auth.models import User, AbstractUser

class Userinfo(AbstractUser):
    phone = models.CharField(max_length=32)
    avatar = models.CharField(max_length=32)

之后到数据库中看一眼,发现已经没有auth_user表了, 我们创建的表替代了它,并且最后也有了我们自己定义的字段。 

四、 AbstractBaseUser扩展auth_user表

上面讲了AbstractUser,看源码得知AbstractUser是继承了AbstractBaseUser。

如果还觉得AbstractUser帮我们建了太多的字段,那么可以考虑使用以下AbstractBaseUser。它大概和上面的AbstractUser配置一样。

 建表:models.py

 创建后的所有表字段:可以看到,django只是帮我们新建了id,password,last_login三个字段而已。

在模型类中我们必须定义一个用户名字段,并指定属性为unique,然后告诉django这个字段是用户名字段:

username = models.CharField(max_length=32,unique=True)
USERNAME_FIELD = 'username'

# 这当中的username你可以任意命名,unique必须指定为True

 如果不写这两句话,你会发现执行数据库迁移命令怎么创建表都没办法创建出来,一直报错:

AttributeError: type object 'UserInfo' has no attribute 'USERNAME_FIELD'
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值