Django一分钟:借助Django的认证系统快速实现RBAC权限校验以及Session会话

引言

Django自带一套认证与权限系统帮助我们快速的实现RBAC权限控制。今天我们要讨论的是Django的认证与权限系统怎么使用,以及Django在背后为我们做了些什么。

一、权限系统会创建数据库表

如果使用了Django的认证系统(在settings中注册app'django.contrib.auth'),初次执行migrate迁移,Django会自动在数据库中创建5张表:用户、权限、组以及三者两两之间的关系表。这在RBAC权限管理系统的数据库表设计中非常常见。

  • user
  • group
  • permission
  • user_group
  • group_permission
  • user_permission

在使用Django的认证系统我们需要知道以下几件事:

  1. 我们可以自己在permission表中创建一些权限,但通常来说不需要,Django在执行数据库迁移时,会自动为已注册app的模型创建增、删、改、查四个权限。
  2. 我们可以为用户分配权限,本质上就是在user_permission关系表中创建一条数据。我们也可以创建一个组,你可以将组命名为"采购部门",为组分配权限,被分配到这个组中的用户将自动获取这个组的权限。
  3. 通过createsuperuser 创建的超级用户会拥有所有的权限(准确来说是自动通过权限认证),普通用户的权限需要自己分配。

二、创建和验证用户

我们可以直接使用Django中的User模型创建用户。创建组和权限也是一样的做法,它们都是普通的模型,只不过Django提前帮我们写好了。

python 复制代码
from django.contrib.auth.models import User
user = User.objects.create_user("john", "lennon@thebeatles.com", "johnpassword")

Django不在数据库中存储用户的明文密码,(不在数据库中存储用户的明文密码是基本常识),而是存储散列值。

验证用户密码需要通过内置的authenticate方法,验证成功会获取获取到对应User对象,在登录的步骤中我们会用到此方法:

python 复制代码
from django.contrib.auth import authenticate

user = authenticate(username="john", password="secret")
if user is not None:
    print("验证成功")
else:
    print("验证失败")

可以重置密码:

python 复制代码
from django.contrib.auth.models import User
u = User.objects.get(username="john")
u.set_password("new password")
u.save()

查看用户权限直接使用user对象的has_perm方法:

python 复制代码
user.has_perm("myapp.change_blogpost")

三、登录、登出与会话

Django使用Session(会话)和中间件将身份验证系统和请求对象request连接在一起

当请求进来时,我们在视图函数中可以获取到request: HttpRequest我们可以检查user是否通过授权,即是否登录。

python 复制代码
if request.user.is_authenticated:
    print("已登录用户")
else:
    print("未登录用户")

用户登录需要调用login()方法。该方法会为传入的user对象在数据库的session表中创建一条数据,这代表该用户的会话信息,会话可以控制用户的登录状态。Django会将SessionID设置到响应头中的SET-COOKIE字段里返回给用户的浏览器客户端,这样浏览器客户端就会自动存储用户cookie,并为用户以后的每条请求带上cookie,我们后端就能区分用户的身份和会话状态了。

python 复制代码
from django.contrib.auth import authenticate, login
ef my_view(request):
    username = request.POST["username"]
    password = request.POST["password"]
    user = authenticate(request, username=username, password=password)
    if user is not None:
        # 用户通过验证之后就执行登录函数
        login(request, user)

登出只需对请求对象使用logout方法:

python 复制代码
def logout_view(request):
    logout(request)

四、权限控制

我们可以通过不同的方法检查用户是否登录:

  1. 通过request.user.is_authenticated方法:
python 复制代码
def my_view(request):
    if not request.user.is_authenticated:
        return render(request, "myapp/login_error.html")
  1. 通过@login_required装饰器:

你需要设置settings.LOGIN_URL控制未登录用户被重定向的页面

python 复制代码
from django.contrib.auth.decorators import login_required


@login_required
# @login_required(login_url="/accounts/login/")
def my_view(request): ...
  1. 在视图类中使用LoginRequiredMixin
python 复制代码
from django.contrib.auth.mixins import LoginRequiredMixin


class MyView(LoginRequiredMixin, View):
    # 可选配置
    login_url = "/login/"
    redirect_field_name = "redirect_to"

控制权限方法也类似:

  1. 直接检查
python 复制代码
def my_view(request):
    if not request.user.has_perm("myapp.change_blogpost"):
        print("用户无权更改blogpost")
  1. 使用装饰器
python 复制代码
from django.contrib.auth.decorators import permission_required

@permission_required("polls.add_choice")
def my_view(request): ...

你可以提供raise_exception参数,装饰器将会触发PermissionDenied,从而触发403(HTTP Forbidden)视图,比较常用:

python 复制代码
from django.contrib.auth.decorators import login_required, permission_required

@login_required
@permission_required("polls.add_choice", raise_exception=True)
def my_view(request): ...
  1. 在视图类中使用PermissionRequiredMixin
python 复制代码
from django.contrib.auth.mixins import PermissionRequiredMixin


class MyView(PermissionRequiredMixin, View):
    permission_required = "polls.add_choice"
    # 或者:
    permission_required = ["polls.view_choice", "polls.change_choice"]

总结

  • Django会在数据库中创建辅助认证和会话系统的表。
  • 用户登录和登出会自动创建和删除会话。
  • 在视图中获request对象手动对用户的身份和权限进行验证,Django内置的装饰器和混入类可以给我们提供帮助。
相关推荐
BullSmall7 分钟前
第三方软件安全-Dependency‑Track Docker 部署
安全·docker·容器
AImatters41 分钟前
国产算力底座,支撑油气储运数字化迈过关键分水岭
安全·cpu·算力·海光·油气储运
傲笑风1 小时前
【openvino】tinybert基于openvino服务化部署(四)
人工智能·python·自然语言处理·nlp·bert·openvino
维基框架2 小时前
WIKI 知识库 v1.1.1 正式发布
人工智能·python
Mr数据杨3 小时前
【Codex】用下载中心模块管理系统导出文件与下载任务
django·codex·项目开发
叠叠乐4 小时前
中国移动家庭云电脑window关闭所有安全脚本
安全
Jmyd01234 小时前
实训室的 3D 模型涉及肖像文物,数据安全与合规怎么做?
安全·3d·数据安全·虚拟实训
芯盾时代4 小时前
《金融业网络安全管理办法(征求意见稿)》全条款深度拆解(三)
网络·安全·网络安全
敢敢是只喵i5 小时前
一个本地 AI Agent 要操作多个门店或 SaaS 账号,应该怎样安全切换身份?
人工智能·安全·ai·系统架构·业界资讯
Acrel12345 小时前
DC800V 大规模落地,算力机房安全该如何保障
安全