前言
auth是Django自带的用户认证模块,用于用户的身份验证功能。
auth模块是cookie和session的升级版,auth模块是对登录认证方法的一种封装,之前我们获取用户输入的用户名及密码后需要自己从user表里查询有没有用户名和密码符合的对象,而有了auth模块之后就可以很轻松的去验证用户的登录信息是否存在于数据库中。除此之外,auth还对session做了一些封装,方便我们校验用户是否已登录。
Django 用户认证(Auth)组件需要导入 auth 模块:
# 认证模块
from django.contrib import auth
# 对应数据库
from django.contrib.auth.models import User
数据库中对应的表:
用户登录后:会在django_session中session id,并且把用户信储存起来
数据库方式创建用户:
创建用户对象的三种方法:
- create():创建一个普通用户,密码是明文的。
- create_user():创建一个普通用户,密码是密文的。
- create_superuser():创建一个超级用户,密码是密文的,要多传一个邮箱 email 参数。
参数说明:
- username: 用户名。
- password:密码。
- email:邮箱 (create_superuser 方法要多加一个 email)。
- 往数据库中加入用户:
from django.contrib.auth.models import User
User.objects.create(username='runboo',password='123') # 方式一
User.objects.create_user(username='runbooo',password='123') # 方式二
User.objects.create_superuser(username='runbooo',password='123') # 方式三
执行程序后,数据库中信息:
方式一:
方式二:
方式三:
密码加密、效验方法
当数据库中的密码是加密状态时,加密过的密码不能直接解密。
Django内部专门提供了两个方法:
-
make_password(明文密码) 结果返回一个加密后的字符串;
-
check_password('明文密码', '加密后的字符串') 进行密码验证,结果返回True/False。
# 导入方式
from django.contrib.auth.hashers import make_password, check_password
make_pwd = make_password('123456') # 返回加密过的密码字符串
check_pwd = check_password('123456', make_pwd) # 明文密码和加密字符串进行效验
修改密码方式
-
set_password()
该方法只能验证 auth 默认数据库;如果自己写表,只能自己验证后自己修改。
from django.contrib.auth.models import User
# 修改密码方式:
user = User.objects.get(id=1) # 获取用户信息
user.set_password('654321') # 改新密码
user.save() # 保存修改结果
验证密码修改是否完成:
from django.contrib.auth.models import User
from django.contrib.auth.hashers import make_password, check_password
user = User.objects.get(id=1) # 获取用户信息
u = make_password('654321') # 明文密码加密
check = check_password('654321', user.password) # 效验密码,user.password:获取数据中的数据
Models.User 的字段
res = request.user
requset 是视图函数 def xx(request) 中的参数
字段 | 说明 |
---|---|
res.id | ID号 |
res.password | 密码 |
res.username | 用户名 |
res.email | 邮箱 |
res.last_login | 上次登录时间,到毫秒,默认空 |
res.last_name | 姓,150字段以内,可选 |
res.first_name | 名字,30字符以内,可选 |
res.is_superuser | 是否超级用户,返回bool |
res.is_staff | 指定该用户是否可以访问管理站点,返回bool |
res.is_active | 是否为活动状态, |
res.date_joined | 指定用户创建日期,默认为当前日期 |
res.groups | 与 django.contrib.auth.models.Group 多对多 关系 |
res.user_permissions | 与 django.contrib.auth.models.Permissions 多对多 关系 |
Models.User 属性
- 验证用户是否已登录:
res.is_authenticated
# 不加括号
1.只是一种判断用户是否已通过身份验证的方法。
2.不效验权限问题,不检查用户是否处于活动状态或具有有效的回话。
3.每个视图函数的 request.user 对象都有这个方法。
4.验证使用: request.user.is_authenicated()
5.若要指定跳转页面可在 settings.py 中指定 LOGIN_URL = "/login/"
auth模块常用方法
导入模块方式: from django.contrib import auth
authenticate()
提供了用户认证功能,即验证用户名以及密码是否正确,一般需要username 、password两个关键字参数。
如果认证成功(用户名和密码正确有效),便会返回一个 User 对象,否则返回 None。
示例:
点击查看代码
from django.contrib.auth import authenticate, login
def login(request):
if request.method == "POST":
user = request.POST.get("user")
pwd = request.POST.get("pwd")
# 对用户进行验证,验证成功,返回user对象,否则返回None
user = auth.authenticate(username=user,password=pwd)
# 成功挑战指定页面
if user:
# 将登录之后的数据封装到 request.user 中可供其他用户调用
auth.login(request,user) #session写操作
return redirect("/index/")
return render(request,"longin.html") # 跳转登录页面
login(HttpRequest, user)
该函数实现一个用户登录的功能。它本质上会在后端为该用户生成相关session数据。
该函数接受一个HttpRequest对象,以及一个经过认证的User对象。
示例:
点击查看代码
from django.contrib.auth import authenticate, login
def my_view(request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
# 重定向到成功页面.
...
else:
# 返回“无效登录”错误消息
...
logout(request)
当调用该函数时,当前请求的session信息会全部清除。该用户即使没有登录,使用该函数也不会报错。
该函数接受一个HttpRequest对象,无返回值。
示例:
点击查看代码
from django.contrib.auth import logout
def logout_view(request):
logout(request) # 重定向到成功页面
is_authenticated()
用来判断当前请求是否通过了认证。
在网站开发过程中,经常会遇到这样的需求:
- 用户登陆后才能访问某些页面
- 如果用户没有登录就访问该页面的话直接跳到登录页面
- 用户在跳转的登陆界面中完成登陆后,自动访问跳转到之前访问的地址
示例:
点击查看代码
# 直接用auth的is_authenticated方法验证
def my_view(request):
if not request.user.is_authenticated():
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
# 根据request.user.username来验证,如果为空,则说明没有登录
def my_view(request):
if not request.user.username:
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):
...
login_required
auth 给我们提供的一个装饰器工具,用来快捷的给某个视图添加登录校验。
说明:
- 使用时只要在需要登录的函数上,写入该装饰器即可;
- 跳转的登录页地址可以在 settings.py 中配置: LOGIN_URL = "/login/"
点击查看代码
from django.contrib.auth.decorators import login_required
@login_required
def index(request):
name = request.user
# 登录成功后的页面
return HttpResponse('登录成功,用户:%s' %name)
如果用户没有登录,会重定向到 settings.LOGIN_URL ,并传递绝对路径到查询字符串中:/accounts/login/?next=/index/ ;next 保存用户登录之前访问的URL,问号前面才是 settings.LOGIN_URL 配置的URL地址。
login_required 参数说明
login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None)
a. redirect_field_name
默认情况 ,成功验证时用户跳转的路径保存在 next 中。如果想修改需要在 login_required()
中传递参数:redirect_field_name='自定义名称'
。
from django.contrib.auth.decorators import login_required
@login_required(redirect_field_name="my_name") # 只有此函数生效该地址
def index(request):
name = request.user
# 登录成功后的页面
return HttpResponse('登录成功,用户:%s' %name)
结果访问的URL是: /accounts/login/?my_name=/index/ (没有配置LOGIN_URL)
- 配置 settings.URL(全局)
LOGIN_URL = "/login/" # 自定义登录页地址
这时候的访问URL地址为: /login/?my_name=/index/
注意:如果修改了 redirect_field_name
默认参数,则可能也需要自定义登录模板,因为存储重定向路径的模板上下文变量使用的是 redirect_field_name
值,而不是 “next” (默认情况)。
b.login_url
from django.contrib.auth.decorators import login_required
@login_required(login_url="/abc/login/") # 只有此函数生效该地址
def index(request):
name = request.user
# 登录成功后的页面
return HttpResponse('登录成功,用户:%s' %name)
结果访问的地址: /abc/login/?next=/index/
注意:如果没有指定参数 login_url ,则需要确认 settings.LOGIN_URL 和登录视图函数是否正确关联。
用户表扩展字段
继承的方式:
-
如果使用继承方式,要使用 auth 模块话,需要在 settings.py 中进行配置:
AUTH_USER_MODEL = "app01.UserInfo" # 指定 UserInfo 为认证表
2. 创建用户认证表:
注意:表不在继承 models.Model 类,改为继承: AbstractUser
类
from django.db import models
from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
phone = models.CharField(max_length=11, blank=True, help_text='请输入手机号') # 扩展的字段
addr = models.CharField(max_length=32, blank=True, help_text='请输入地址')
# blank=False 为必填字段
class Meta(AbstractUser.Meta):
# 需要继承之前的 Meta 否则有些不生效
db_table = "user_login_info_tables"
-
执行命令创建表:
D:\mysite $ python manage.py makemigrations D:\mysite $ python manage.py migrate
admin 修改源码
如果想要在 admin 管理后台中显示用户认证表中自定义的字段时,这就需要自己手动改源码。
- 进入 admin 文件: django/contrib/auth/admin ,修改如下内容:
点击查看代码
# 1. 修改: 第9行
from django.contrib.auth.models import Group, User
改为: from django.contrib.auth.models import Group
# 2. 新增一行:导入自己写的用户认知表,
from app01.models import UserInfo as User # 注意:加 as User 是为了后面的代码可以直接使用
- 该文件中找到
class UserAdmin(admin.ModelAdmin)
类,在下面 fieldsets 元组中添加一列:("标题名", {'fields': ('自定义字段1', '自定义字段2')}) ,以下示例:
点击查看代码
class UserAdmin(admin.ModelAdmin):
add_form_template = 'admin/auth/user/add_form.html'
change_user_password_template = None
fieldsets = (
(None, {'fields': ('username', 'password')}),
(_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
(_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser',
'groups', 'user_permissions')}),
(_('Important dates'), {'fields': ('last_login', 'date_joined')}),
# 新增的内容:
("phone_addr", {"fields": ("phone", "addr")}),
)
修改后重启服务器进入页面显示:
auth 权限管理
auth 默认有个权限管理模块。auth 权限控制的其实就是对表的增删改查。
auth 的权限添加模式:
- 给用户直接设置权限
- 给组绑定权限,然后将用户添加进组内(用户可以有多个组)
权限管理操作方法:
- add 增
- delete 删除
- change 改
- views 查
默认的命名规则:权限名_类名小写 (类名来自于 django_content_type 数据表中的 model 字段)
- auth 的三个model类:
from django.contrid.auth.models import User
# 用户类,继承 django.contrib.auth.models.AbstractUser
from django.contrid.auth.models import Group
# 用户组类,储存用户组数据
from django.contrid.auth.models import Permission
# 权限类,负责存储全部的权限
- auth 数据表介绍
auth_user 用户表
auth_user_groups 用户所属组的表
auth_user_user_permissions 用户权限表
auth_group 用户组表
auth_group_permissions 用户组权限表
auth_permission 权限表,所有权限
- 默认权限
# app01/models.py
class UserInfo(models.Model):
name = models.CharField(max_length=64)
...
class Meta:
verbose_name = "用户表"
verbose_name_plural = verbose_name
# 默认情况: default_permissions = ('add','change','delete','view')
# 修改默认权限:
default_permissions = ('add_01','change_02','delete_03','view_04')
执行创建表命令后,在 auth_permission 数据表中可以看到修改的内容已添加。
注意: 最好在首次创建表时一起修改。
- 新增额外权限
# app01/models.py
class UserInfo(models.Model):
name = models.CharField(max_length=64)
...
class Meta:
verbose_name = "用户表"
verbose_name_plural = verbose_name
permissions = [
# 添加额外权限
('can_deliver_pizzas', 'can deliver pizzas')
# 在 auth_permission 表中添加权限
# 表中的 codename字段 == can_deliver_pizzas
# 表中的 name字段 == can deliver pizzas
]
verbose_name 字段内容会在 auth_permission 表的name字段加的内容。
添加后表显示结果:
- 创建用户组
from django.contrid.auth.models import Group
# 创建组
group_obj = Group.objects.create(name='group01')
- 给用户添加组
from django.contrid.auth.models import Group,User
# 将用户添加进组
u_obj = User.objects.get(id=1) # 1.查找用户
g_obj = Group.objects.get(id=1) # 2. 查找组
u.obj.groups.add(g_obj) # 3.添加
# 查看用户的组
u1 = User.objects.filter(id=1).values('groups_name') # 方式一 查看用户的所有组
u2 = User.objects.get(id=1).groups.all() # 方式二
- 给组添加权限
from django.contrid.auth.models import Group, Permission
# 找到需要添加的权限
per = Permission.objects.filter(id__in=[1,4,16,27])
# 找到需要加权限的组
group_obj = Group.objects.get(id=1) # id=1 是对应的组id
# 将权限赋予组
group_obj.Permission.add(*per)
# 查看某个用户组权限
g1 = Group.objects.get(id=1).Permissions.all() # 返回queryset对象
# 查看用户所有的组权限
g2 = Group.objects.filter(id=1).values("permissions_codename")
- 查看用户权限
from django.contrid.auth.models import User
u = User.objects.get(id=1)
# 查用户全部权限
u.get_all_permissions()
# 查看用户所在组的全部权限
u.get_group_permissions() # 返回集合格式
# 查看用户 不包含组的全部权限
from django.contrib.auth.backends import ModelBachend
mm = ModelBachend() # 实例化
mm.get_user_permissions(u) # 查找权限