Django rest_framework用户认证和权限
完整的代码
https://gitee.com/mom925/django-system
使用jwt实现用户认证
pip install djangorestframework-simplejwt
重新定义一下User类
class Users(AbstractUser):
class Meta:
db_table = "system_users"
verbose_name = "用户表"
verbose_name_plural = verbose_name
ordering = ("-create_datetime",)
GENDER_CHOICES = (
(0, "未知"),
(1, "男"),
(2, "女"),
)
username = models.CharField(max_length=150, unique=True, db_index=True, verbose_name="用户账号", help_text="用户账号")
nickname = models.CharField(max_length=50, verbose_name="昵称", null=True, blank=True, help_text="昵称")
email = models.EmailField(max_length=255, verbose_name="邮箱", null=True, blank=True, help_text="邮箱")
mobile = models.CharField(max_length=255, verbose_name="电话", null=True, blank=True, help_text="电话")
avatar = models.CharField(max_length=255, verbose_name="头像", null=True, blank=True, help_text="头像")
gender = models.IntegerField(choices=GENDER_CHOICES, default=0, verbose_name="性别", null=True, blank=True, help_text="性别")
create_datetime = models.DateTimeField(auto_now_add=True, verbose_name="创建时间", null=True, blank=True, help_text="创建时间")
role = models.ManyToManyField(to="Role", blank=True, verbose_name="关联角色", db_constraint=False, help_text="关联角色")
并在 settings.py 加入
AUTH_USER_MODEL = 'system.Users'
USERNAME_FIELD = "username"
设置全局的默认认证和权限 在settings.py 配置 REST_FRAMEWORK
REST_FRAMEWORK = {
"DEFAULT_PERMISSION_CLASSES": [
"rest_framework.permissions.IsAuthenticated", # 只有经过身份认证确定用户身份才能访问
],
'DEFAULT_AUTHENTICATION_CLASSES': [
"rest_framework_simplejwt.authentication.JWTAuthentication",
],
}
接下来需要获取用户的token
先配置获取token和刷新token的路由
path('login/', views.LoginView.as_view(), name='登录'),
path('refresh/', views.CustomTokenRefreshView.as_view(), name='刷新token'),
接下来重写一下登录的序列器
class LoginSerializer(TokenObtainPairSerializer):
"""
登录的序列化器:
""" class Meta:
model = Users
fields = "__all__"
read_only_fields = ["id"] def validate(self, attrs):
if settings.AUTH_CAPTCHA:
captcha = self.initial_data.get("captcha", None)
captchaKey = self.initial_data.get("captchaKey", None)
if captcha is None:
raise CustomValidationError(detail='验证码不能为空')
cache_captcha = cache.get('captcha_' + captchaKey)
if cache_captcha is None:
raise CustomValidationError(detail='验证码过期')
if str(captcha) != str(cache_captcha):
raise CustomValidationError(detail='验证码不正确')
cache.delete('captcha_' + captchaKey)
data = super().validate(attrs)
data["user_name"] = self.user.username
data["user_id"] = self.user.id
data['avatar_url'] = get_avatar_url(self.user.avatar) if self.user.avatar else self.user.avatar
request = self.context.get("request")
request.user = self.user
request_save_log(request, {'action': '用户登录', 'describe': '用户账号密码登录'})
return {"code": 1, "msg": "success", "data": data}
登录视图
class LoginView(TokenObtainPairView):
"""
tags:
登录
"""
serializer_class = LoginSerializer
authentication_classes = []
permission_classes = []
刷新token视图
class CustomTokenRefreshView(TokenRefreshView):
"""
tags:
刷新token
"""
def post(self, request, *args, **kwargs):
refresh_token = request.data.get("refresh")
try:
token = RefreshToken(refresh_token)
data = {
"access": str(token.access_token),
"refresh": str(token)
}
except:
return ErrorResponse(msg='error')
return SuccessResponse(data=data)
自定义一下后台的认证,使用自定义后台认证需要在settings.py 中加入 AUTHENTICATION_BACKENDS = ["utils.backend.CustomBackend"]
class CustomBackend(ModelBackend):
"""
Django原生认证方式
""" def authenticate(self, request, username=None, password=None, **kwargs): if username is None:
username = kwargs.get(UserModel.USERNAME_FIELD)
if username is None or password is None:
return
try:
user = UserModel._default_manager.get_by_natural_key(username)
except Exception:
pass
# print(traceback.format_exc())
# except UserModel.DoesNotExist:
# # Run the default password hasher once to reduce the timing
# # difference between an existing and a nonexistent user (#20760).
# UserModel().set_password(password)
else:
if user.check_password(password):
if self.user_can_authenticate(user):
return user
else:
raise CustomValidationError("当前用户已被禁用,请联系客服或管理员!")
登录成功

自定义权限
定义权限和角色模型
class Role(models.Model):
class Meta:
db_table = "system_role"
verbose_name = "角色表"
verbose_name_plural = verbose_name
ordering = ("sort",)
name = models.CharField(max_length=64, verbose_name="角色名称", help_text="角色名称")
sort = models.IntegerField(default=1, verbose_name="角色顺序", help_text="角色顺序")
status = models.BooleanField(default=True, verbose_name="角色状态", help_text="角色状态")
admin = models.BooleanField(default=False, verbose_name="是否为admin", help_text="是否为admin")
remark = models.TextField(verbose_name="备注", help_text="备注", null=True, blank=True)
permission = models.ManyToManyField(to="Permission", verbose_name="关联权限", db_constraint=False, help_text="关联权限") class Permission(models.Model):
class Meta:
db_table = "system_permission"
verbose_name = "权限表"
verbose_name_plural = verbose_name
ordering = ("-value",) METHOD_CHOICES = (
(0, "GET"),
(1, "POST"),
(2, "PUT"),
(3, "DELETE"),
)
name = models.CharField(max_length=64, verbose_name="名称", help_text="名称")
value = models.CharField(max_length=64, verbose_name="权限值", help_text="权限值")
api = models.CharField(max_length=200, verbose_name="接口地址", help_text="接口地址")
method = models.IntegerField(default=0, verbose_name="接口请求方法", null=True, blank=True, help_text="接口请求方法") class ApiWhiteList(models.Model):
class Meta:
db_table = "api_white_list"
verbose_name = "接口白名单"
verbose_name_plural = verbose_name
ordering = ("-create_datetime",) METHOD_CHOICES = (
(0, "GET"),
(1, "POST"),
(2, "PUT"),
(3, "DELETE"),
)
url = models.CharField(max_length=200, help_text="url地址", verbose_name="url") method = models.IntegerField(default=0, verbose_name="接口请求方法", null=True, blank=True, help_text="接口请求方法")
enable_datasource = models.BooleanField(default=True, verbose_name="激活数据权限", help_text="激活数据权限", blank=True)
create_datetime = models.DateTimeField(auto_now_add=True, verbose_name="创建时间", null=True, blank=True, help_text="创建时间")
自定义的权限可以继承 BasePermission 自己定义其中的逻辑,例如:
class CustomPermission(BasePermission):
"""自定义权限""" def has_permission(self, request, view):
if isinstance(request.user, AnonymousUser):
return False
# 判断是否是超级管理员
if request.user.is_superuser:
return True
else:
api = request.path # 当前请求接口
method = request.method # 当前请求方法
methodList = ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'PATCH']
method = methodList.index(method)
# ***接口白名单***
api_white_list = ApiWhiteList.objects.filter(enable_datasource=True).values(permission__api=F('url'), permission__method=F('method'))
api_white_list = [
str(item.get('permission__api').replace('{id}', '([a-zA-Z0-9-]+)')) + ":" + str(
methodList.index(item.get('permission__method', 'GET'))) + '$' for item in api_white_list if item.get('permission__api')]
# ********#
if not hasattr(request.user, "role"):
return False
userApiList = request.user.role.values('permission__api', 'permission__method') # 获取当前用户的角色拥有的所有接口
ApiList = [
str(item.get('permission__api').replace('{id}', '([a-zA-Z0-9-]+)')) + ":" + str(
item.get('permission__method')) + '$' for item in userApiList if item.get('permission__api')]
new_api_ist = api_white_list + ApiList
new_api = api + ":" + str(method)
# print(api, new_api, method, new_api_ist)
for item in new_api_ist:
matchObj = re.match(item, new_api, re.M | re.I)
if matchObj is None:
continue
else:
return True
else:
return False
使用时可以在视图的 permission_classes = [CustomPermission] 加入到列表中
Django rest_framework用户认证和权限的更多相关文章
- python 全栈开发,Day79(Django的用户认证组件,分页器)
一.Django的用户认证组件 用户认证 auth模块 在进行用户登陆验证的时候,如果是自己写代码,就必须要先查询数据库,看用户输入的用户名是否存在于数据库中: 如果用户存在于数据库中,然后再验证用户 ...
- COOKIE与SESSION、Django的用户认证、From表单
一.COOKIE 与 SESSION 1.简介 1.cookie不属于http协议范围,由于http协议无法保持状态,但实际情况,我们却又需要“保持状态”,因此cookie就是在这样一个场景下诞生. ...
- Django--分页器(paginator)、Django的用户认证、Django的FORM表单
分页器(paginator) >>> from django.core.paginator import Paginator >>> objects = ['joh ...
- Django Rest Framework(认证、权限、限制访问频率)
阅读原文Django Rest Framework(认证.权限.限制访问频率) django_rest_framework doc django_redis cache doc
- 深入一下Django的用户认证和cache
深入一下Django的用户认证和cache 用户认证 首先明白一个概念,http协议是无状态的,也就是每一次交互都是独立的,那如何让服务器和客户端进行有状态的交互呢,现在较为常见的方法就是让客户端在发 ...
- 【django之用户认证】
一.auth模块 模块导入 from django.contrib import auth 主要方法如下: 1 .authenticate() 提供了用户认证,即验证用户名以及密码是否正确,一般 ...
- Django组件-用户认证
用户认证 一.auth模块 from django.contrib import auth django.contrib.auth中提供了许多方法,这里主要介绍其中的三个: 1.1 .authenti ...
- Django之用户认证组件
auth模块 之前我们在进行用户登录验证的时候,都是自己写代码,接收用户提交的数据,然后去数据库取数据进行匹配验证,其实Django已经给我们提供了内置的用户认证功能.不信的话你可以打开models. ...
- Django框架----用户认证auth模块
一.auth模块 auth模块:针对auth_user表 创建超级管理用户命令: Python manage.py createsuperuser添加用户名添加密码(至少8位)确认密码添加邮箱(可为空 ...
- Django之用户认证功能
前言 做web应用对登录做用户身份认证,然后设置session是必不可少的,因为我们就需要把有权限访问本站视图的用户,单独建一张表记录到数据库里: Django作为一个大而全的框架,已经为我们做好了这 ...
随机推荐
- 题解 CF1004C
题意描述: 给定 \(n\) 个数,从前往后找,看看能和后面的数组成多少个不同的数对. 若两个数对仅仅是位置不同,我们也认为是两个不同的数对. 题目分析: 阅读题目,我们不难看出,若前面有一个数已经出 ...
- 编译wasm Web应用
刚学完WebAssembly的入门课,卖弄一点入门知识. 首先我们知道wasm是目标语言,是一种新的V-ISA标准,所以编写wasm应用,正常来说不会直接使用WAT可读文本格式,更不会用wasm字节码 ...
- base64编码的学习
base64编码是什么 Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法. Base64编码本质上是一种将二进制数据转成 ...
- Vue打包发布
打包发布 目标:明确打包的作用 说明:vue脚手架只是开发过程中,协助开发的工具,当真正开发完了,脚手架不参与上线 打包的作用: 将多个文件压缩合并成一个文件 语法降级 less sass ts 语法 ...
- 快速下载vscode、git
在官网下载vscode太慢,解决方式: http://vscode.cdn.azure.cn/stable/ea3859d4ba2f3e577a159bc91e3074c5d85c0523/VSCod ...
- C/S结构用户界面设计
C/S结构用户界面设计 [实验编号] 10003809547j 图形用户界面设计 [实验学时] 8学时 [实验环境] l 所需硬件环境为微机: l 所需软件环境为Microsoft Visual S ...
- MySQL8.0 安装教程
一.下载 1.官网地址 MySQL :: Download MySQL Community Server 2.选择安装包安装方式 3.选择安装版本 4.开始下载 5.下载成功 二.安装 1.双击安装包 ...
- 0x01.web请求、web环境、抓包技巧
网站搭建 DNS解析 域名选择 http/https 证书 服务器 web应用环境架构 操作系统 linux windows 开发语言 php java ASP/ASPX python等 程序源码 C ...
- 【大语言模型基础】60行Numpy教你实现GPT-原理与代码详解
写在前面 本文主要是对博客 https://jaykmody.com/blog/gpt-from-scratch/ 的精简整理,并加入了自己的理解. 中文翻译:https://jiqihumanr.g ...
- Vulntarget-b-wp
Vulntarget-b 环境配置 centos7 用户 密码 root root vulntarget root 宝塔Linux面板http://192.168.0.104:8888/045b276 ...