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作为一个大而全的框架,已经为我们做好了这 ...
随机推荐
- 看完包你搞懂Redis缓存穿透、击穿和雪崩!!!说到做到
缓存穿透 缓存穿透是指当用户对Redis发出无效或者不存在的数据信息操作时,这条数据在Redis中不存在,Redis就会在MySQL数据库中查询,可时无效的信息在mysql数据库中也不存在,就会造成R ...
- Ansible自动化部署工具-role模式安装filebeat实际案例分析
大家好,我是蓝胖子,前面一节我简单的讲了讲Ansible的架构和编排任务的语法,可以发现,通过playbook方式编排任务时,能够将任务文档化,但是在面对比较复杂且不同业务的任务编排时,维护playb ...
- linux开发基于iMX6ULL-uboot编译环境配置
1.下载半导体官方的uboot和linux内核固件 2.下载uboot 3.下载linux内核(选择5.4版本的分支下载) 下载后如下所示 解压后如下 查看文件夹中的内容 创建一个git仓库然后开始自 ...
- Java 面试题之 Logback 打印日志是如何获取当前方法名称的?
在 Java 中,有四种方法可以获取当前正在执行方法体的方法名称,分别是: 使用 Thread.currentThread().getStackTrace() 方法 使用异常对象的 getStackT ...
- bad_python
对着正确的pyc文件在010把题目文件的前缀改掉,然后在线反编译得到代码
- 在Linux平台下使用.NET Core访问Access数据库读取mdb文件数据
在 Linux平台下使用 .NET Core 访问 Access数据库 读取 mdb文件 数据 今天有群友在群里问 C# 能不能在 Linux 下访问 Access数据库? 我觉得这很有趣,因此研究折 ...
- 根据子节点ID获取结构树中该子节点的所有父节点ID
数据源: let adreeJson = [{ cat_id: 1, cat_name: '大家电', cat_pid: 0, cat_level: 0, cat_deleted: false, ch ...
- 【uniapp】【微信小程序】【外包杯】如何创建分包
意义:分包可以减少小程序数次启动时的加载时间 1.创建分包的根目录 2.在page.json中,和pages节点平级的位置声明节点,用来定义分包的相关结构 3.在subpkg目录上新建页面 4.完成了
- Stream API学习笔记
Java8 中Stream API介绍 Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象.这种风格将要处理的元素集合看作一种流, ...
- rust 过程宏
简介 Rust 编程语言里面有两种宏系统,一种是声明宏(Declarative Macros),另一种为过程宏(Procedural Macros).声明宏和过程宏是两种基本上完全不一样的宏系统,编写 ...