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作为一个大而全的框架,已经为我们做好了这 ...
随机推荐
- source insight 中添加指定类型文件
以下为source insight 3.X版本的设置方法: source insight 中过滤某些格式的文件. 建立source insight工程后,先暂时不要急于添加文件. 打开options- ...
- 动态规划——提高Ⅴ(DP优化)
单调队列优化DP 其实单调队列就是一种队列内的元素有单调性(单调递增或者单调递减)的队列,答案(也就是最优解)就存在队首,而队尾则是最后进队的元素.因为其单调性所以经常会被用来维护区间最值或者降低DP ...
- L3-011 直捣黄龙
#include<bits/stdc++.h> using namespace std; using pii = pair<int, int>; const int N = 3 ...
- C语言已知单链表LA=(a1,a2,…,am)和LB=(b1,b2,…,bn),编写程序按以下规则将它们合并成一个单链表LC,
LC=(a1,b1,-,am,bm,bm+1,-,bn),m<=n 或者 LC=(a1,b1,-,bn,an,an+1,-,am),m>n /* 开发者:慢蜗牛 开发时间:2020.6.1 ...
- LabVIEW基于机器视觉的实验室设备管理系统(3)
目录 行动计划 创建用户信息数据库 后面板连线 初始化 确认修改 确认id 判断旧密码是否正确 判断两次输入的新密码是否相同 修改用户数据库中的密码 结尾 效果演示 上一期我们完成了欢迎登录和信息查询 ...
- 开源推荐,灵活多变功能强大的CMDB
一个完善的基础资源数据库是我们构建运维自动化上层应用的基础,所以构建CMDB系统成了有想法在DevOps运维自动化领域有所发展的企业离不开的重要一环,但受制于每家企业不同的内外部环境.资源配置以及管理 ...
- 【Javaweb】implements Serializable是什么意思?反序列化是什么意思?
为了保证数据传输的可靠 性,常常要implements Serializable,为什么? 对象本质上是虚无缥缈的,只是内存中的一个地址,如果想要让对象持久化,让对象在网络上传输,总不可能传送一个内存 ...
- java 405_Http状态405-方法不允许
解决方法: 删除下列代码. super.doGet(req.resp); super.doPost(req.resp); 分析: 405错误一般指请求method not allowed 错误. 请求 ...
- 一道入门的java安全题
[XCTF]Zhuanxv 收获 java题的一般流程 HQL注入 SQL注入 看题 目录扫描 dirsearch扫目录,发现list目录: 一个登录界面,本着尽量不写sql注入题目的原则(因为太菜了 ...
- MarkdownPad 文件访问权限受限导致软件打开后不久闪退解决方法
近几天发现MarkdownPad有一些小问题,打开时会弹出以下报错信息,告诉你打开文件的权限不够 解决方法如下: 1.复制报错信息中的文件路径"Access to the path 'C:\ ...