9.3 用户认证系统应用
2025-02-17
9.3.1 自定义认证后端
默认,Django系统中仅指定了一个认证后端:ModelBackend,它只简单地比对数据库中存储的用户名和密码是否匹配。这在很多情况下不能够满足需求,所以,Django允许自定义认证后端,并在AUTHENTICATION_BACKENDS中声明即可
认证后端需要实现两个方法的Python类
- get_user:方法接受一个参数,这个参数代表用户对象(不一定是auth.User,Django同样允许自定义用户对象)的主键
- authenticate:将用户身份凭据作为关键字参数,大多数情况下,后端中的关键字参数至少会有usern ame和password
例子:让用户使用“统一密码”通过验证
post应用下新建backends.py文件
from django.contrib.auth.models import User class MasterKeyBackend: def authenticate(self, username=None, password=None): if username and password: try: user = User.objects.get(username=username) if password == "abcdefg": return user except User.DoesNotExist: pass def get_user(self,user_id): try: return User.objects.get(pk=user_id) except User.DoesNotExist: return Nonesettings文件声明
- 列出所有需要的认证后端,例如这里仍然需要指定ModelBackend,否则,系统中只有一个MasterKeyBackend,将不能通过用户名和密码匹配的方式完成用户认证。
- 列表中后端的顺序会影响验证过程。Django使用短路逻辑,当其中的一个后端返回了用户对象时,验证过程就会停止。
# settings AUTHENTICATION_BACKENDS = [ 'django.contrib.auth.backends.ModelBackend', 'post.backends.MasterKeyBackend', ]验证
from django.contrib.auth import authenticate bbs = authenticate(username='bbs', password='bbs_django') bbs.backend # 验证查看使用的验证后端
9.3.2 在模板中校验用户身份和权限
- 传递上下文使用的是ResponseContext时,对于默认的配置,可以在模板中使用user和perms变量
- user变量是User或AnonymousUser类型的实例,不论user是什么类型,都可以使用
is_authenticated方法判断当前用户是否登录 - perms变量是PermWrapper实例,将user进行了包装。使用它可以校验当前用户是否拥有某些权限
1. 在模板中校验用户身份
已经登录的用户,
is_authenticated会返回True,没有登录,返回False{% if user.is_authenticated %} <h1> Hello {{ user.username }}</h1> {% else %} <h1> Hello AnonymousUser</h1> {% endif %}
2. 在模板中校验用户权限
perms变量可以完成两类权限校验
- 是否有某个应用的权限,只要当前用户拥有某个应用中的任何一个权限,即为True。
{{perms.post}}可以返回当前用户被授予的post应用的权限 - 是否有某一项权限,这里指的是当前用户是否有某个确定的权限。例如,
{{perms.post.add_topic}}返回True则代表当前用户拥有post应用中的add_topic权限
- 是否有某个应用的权限,只要当前用户拥有某个应用中的任何一个权限,即为True。
PermWrapper实现了
__contains__方法,可以在模板中使用{% if in %}{% if 'post' in perms %}:{% if 'post.change_topic' in perms %}
{% if perms.post %} <h1> {{ user.username }} has post permission</h1> {% if perms.post.add_topic %} <h2> can add topic </h2> {% endif %} {% if perms.post.change_topic %} <h2> can delete topic </h2> {% endif %} {% else %} <h1> user do not have post permission<h1> {% endif %}
9.3.3 身份验证视图
Web站点提供类似:用户注册,用户登录,修改密码,注销登录等功能,都被称为身份认证视图
- Django内置了身份认证视图,这些视图只需要提供模板即可
1. 自定义用户登录视图
使用用户封路需要使用login方法
- 接受一个HttpRequest参数和一个User参数
用户登录的功能实现主要是两个步骤。
- (1)根据用户传递的凭证(通常是用户名和密码)使用authenticate方法获取用户对象。
- (2)获取到用户对象,使用login方法完成登录,再跳转到自定义的成功页面;没有获取到用户对象,给出错误提示信息。
认证系统内置的用户登录视图同样也是实现了这两个步骤,而且可以指定一些额外的参数控制用户的登录行为。
from django.contrib.auth import authenticate, login def login_view(request): username = request.POST['username'] password = request.POST['password'] # 使用authenticate方法验证用户身份 user = authenticate(username=username, password=password) if user: login(request, user) ... else ...
2. 内置的用户登录视图
- Django在django/contrib/auth/urls.py文件中定义了身份认证视图的URL模式,所以,可以直接将它们include到当前的项目中
- 例如:可以在BBS项目的my_bbs/urls.py文件中添加
path('',include('django.contrib.auth.urls'))- 这样就可以使用Django内置的用户身份验证框架
- 由于内建框架并没有提供模板的实现,所以,需要按照视图定义的位置放置模板文件