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作为一个大而全的框架,已经为我们做好了这 ...
随机推荐
- 从混乱到优雅:基于DDD的六边形架构的代码翻新指南
前言 趁着双十一备战封板,终于又有一些时间可以梳理一下最近的心得. 最近这半年跟同事讨论比较多的是分层架构,然后就会遇到两个触及灵魂的问题,一个是如何做好分层架构,二是DDD在架构层面该如何落地. 为 ...
- 使用Jenkins构建镜像:将应用打包成镜像
学习某册子的CICD,记录使用Jenkins构建镜像的过程. 使用Jenkins集成Git来构建Docker镜像,为后面的部署准备镜像资源. 1. 安装Nodejs环境 如果想要安装Node环境,有以 ...
- 深入了解Rabbit加密技术:原理、实现与应用
一.引言 在信息时代,数据安全愈发受到重视,加密技术作为保障信息安全的核心手段,得到了广泛的研究与应用.Rabbit加密技术作为一种新型加密方法,具有较高的安全性和便捷性.本文将对Rabbit加密技术 ...
- JAVA学习week3
本周由于c++小学期作业.未能按时学习JAVA 主要复习了基本语法 hello word 输出语法 输出格式的选择,进制的转换,注释的选择 还预习了变量相关的知识点
- 黑客玩具入门——4、漏洞扫描与Metasploit
1.Legion漏洞扫描分析工具 Legion是Sparta的一个分支,它是一个开源的.易于使用的.超级可扩展的.半自动的网络渗透测试框架.它是一款Kali Linux系统默认集成的Python GU ...
- 【问题解决】unable to do port forwarding: socat not found
问题复现 前阵子应公司要求做华为云平台的调研,写了一篇文档包含将华为云CCE下载kuberctl配置及使用kubectl转发流量到本地的操作. 今天一早上同事就发来一个错误界面,说是Java远程调试转 ...
- 云端开炉,线上训练,Bert-vits2-v2.2云端线上训练和推理实践(基于GoogleColab)
假如我们一定要说深度学习入门会有一定的门槛,那么设备成本是一个无法避开的话题.深度学习模型通常需要大量的计算资源来进行训练和推理.较大规模的深度学习模型和复杂的数据集需要更高的计算能力才能进行有效的训 ...
- 江西财经大学第一届程序设计竞赛 H题- 小P的数学问题
题目链接:https://www.nowcoder.com/acm/contest/115/H 解题思路:分块打表!!! 什么是分块打表呢??? 从这道题我们知道我们要找到最多1*e9的阶乘 那循环暴 ...
- lca(数链剖分)板子
#include<bits/stdc++.h> #define endl '\n' #define int long long using namespace std; const int ...
- pytest框架学习-测试用例发现机制以及用例执行命令
pytest是什么 pytest是python的一种单元测试框架,与python自带的unittest测试框架类似,但是比unittest框架使用起来更简洁,效率更高. Pytest安装 安装命令: ...