Django 自定义中间件(IP限制频率、用户权限)

【一】用户权限

(1)要求

  • 不同的用户,有不同的操作权限
  • 比如
    • 超级管理员,拥有所有权限
    • 管理员可以增加、查询、修改
    • 普通用户只能查询

(2)逻辑梳理

  • 理论来说,这个权限需要保存在数据库中

    • 但是这里只做演示,在视图函数中定义用户的权限
  • 每个人的权限需要在登录以后才能获得

    • 所以需要创建一个登录界面

    • 在后端的登录逻辑中,根据登录的用户名进行权限查询

    • 由于中间件要进行权限处理,所以这里将权限保存在session中

      • request.session['permission'] = permission
        
  • 中间件逻辑

  • 由于不是所有路径都要限制用户访问

    • 所以需要白名单

    • white_permission_list = ['login', 'register']
      
  • 获取当前访问路径

    • visited_path = request.path
      
  • 由于每次都是直接进入的根路径

    • 所以将根路径也排除在外
  • 循环白名单

    • 使用正则匹配,在白名单的地址不进行权限要求
  • 获取用户可访问的地址

    • user_permission_list = request.session.get("permission")
      user_permission_list = user_permission_list if user_permission_list else []
      
  • 再次循环遍历可访问的地址

    • 使用正则匹配,可访问的地址通过
  • 到最后的就是没有权限的

    • 抛出信息

(3)代码

  • 中间件
import re
import time
from django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixinclass PermissionMiddleWare(MiddlewareMixin):"""限制用户权限"""def process_request(self, request):white_permission_list = ['login', 'register']# 当前访问路径visited_path = request.path# 对根路径进行优先处理if visited_path == "/":return# 对白名单路径进行处理for white_permission in white_permission_list:# 使用正则进行匹配pattern = '/' + white_permission + ".*"pattern = re.compile(pattern=pattern)if re.search(pattern, visited_path):return# 获取登录用户权限user_permission_list = request.session.get("permission")user_permission_list = user_permission_list if user_permission_list else []for permission in user_permission_list:# 使用正则匹配pattern = '/' + permission + '.*'pattern = re.compile(pattern=pattern)if re.search(pattern, visited_path):return# 前面都没有通过,那就是没有权限return HttpResponse("你没有权限访问")
  • 前端
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><form action="" method="post"><p>username:<input type="text" name="username"></p><p>password:<input type="password" name="password"></p><button class="button">提交</button>
</form>
<br>
<div><div><a href="{% url 'login' %}">登录</a></div><div><a href="{% url 'register' %}">注册</a></div><div><a href="{% url 'add_data' %}">添加</a></div><div><a href="{% url 'delete_data' %}">删除</a></div><div><a href="{% url 'revise_data' %}">修改</a></div><div><a href="{% url 'search_data' %}">查询</a></div>
</div>
</body>
</html>
  • 视图层
from django.shortcuts import render, HttpResponseuser_permission_dict = {"super": ['add_data/', 'delete_data/', 'search_data/', 'revise_data/'],"admin": ['add_data/', 'search_data/', 'revise_data/'],"normal": ['search_data/'],
}def login(request):if request.method == "POST":# 获取用户名username = request.POST.get("username")# 查找用户权限,正常应该取数据库中查找,这里简化了permission = user_permission_dict.get(username)permission = permission if permission else []# 保存权限request.session['permission'] = permissionreturn HttpResponse("登录成功")return render(request, 'login.html', locals())def register(request):return HttpResponse("注册界面")
def add_data(request):return HttpResponse("添加界面")
def delete_data(request):return HttpResponse("删除界面")
def revise_data(request):return HttpResponse("修改界面")
def search_data(request):return HttpResponse("查看界面")
  • 路由层
from django.contrib import admin
from django.urls import path
from app01 import viewsurlpatterns = [path('admin/', admin.site.urls),path("", views.login, name='login'),path('register/', views.register, name='register'),path("add_data/", views.add_data, name='add_data'),path("delete_data/", views.delete_data, name='delete_data'),path("search_data/", views.search_data, name='search_data'),path("revise_data/", views.revise_data, name='revise_data'),
]

【二】IP限制访问频率

(1)要求

  • 同一个地址限定时间内访问超过指定次数会抛出异常

(2)思路

  • 要求是限制访问次数

    • 所以这个中间件需process_request方法
  • 首先需要获取到访问的IP地址

    • request.META.get("REMOTE_ADDR")
      
  • 然后获取访问路径

    • request.get_full_path()
      
  • 然后是当前时间的获取

    • time.time()
      
  • 对IP进行判断

    • 如果没有访问过,添加默认信息并保存
    • 如果访问过
      • 判断地址、判断时间
        • 如果时间超过或地址变了,刷新保存信息
        • 如果在时间范围内
          • 访问次数+1
          • 对访问次数进行判断
            • 超过限定次数,返回HttpResponse信息

(3)代码

import time
from django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixinclass SearchMiddleWare(MiddlewareMixin):"""对同一个地址在限定时间内访问超过指定次会抛出异常"""# {'127.0.0.1': {'start_time': 1711525250.3461394, 'visits': 0, "full_path": "/"}}id_data_dict = {}# 最大访问次数visits_limit = 5# 时间间隔time_limit = 10def process_request(self, request):# 获取信息user_id = request.META.get("REMOTE_ADDR")full_path = request.get_full_path()now_time = time.time()# 当前IP第一次访问if user_id not in self.id_data_dict.keys():new_id_dict = {user_id: {"start_time": now_time, "visits": 0, "full_path": full_path}}self.id_data_dict.update(new_id_dict)else:id_data = self.id_data_dict.get(user_id)# 不是同一个地址也刷新# 超过10秒钟重新刷新condition = any([full_path != id_data.get('full_path'),(now_time - id_data.get("start_time")) >= self.time_limit])if condition:id_data['start_time'] = now_timeid_data["visits"] = 0id_data['full_path'] = full_pathself.id_data_dict.update({user_id: id_data})# 访问间隔时间在10秒以内if now_time - id_data.get("start_time") < self.time_limit:# 只要来了就+1id_data["visits"] += 1# 十秒内访问次数超过指定次数,if id_data['visits'] >= self.visits_limit:return HttpResponse("访问频率过高,请稍后在尝试")

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/774359.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React和Vue.js的有什么区别

在当今前端开发领域&#xff0c;React 和 Vue.js 作为两大热门的前端框架备受开发者关注。它们各自拥有独特的特点和优势&#xff0c;在实际项目中有着广泛的运用。本文将深入探讨 React 和 Vue.js 之间的区别&#xff0c;从组件化方式、数据绑定、模板语法以及生态系统和工具支…

案例 | 华院计算x第一财经:我和我的数智人唱双簧

创新关乎命运&#xff0c;科技引领未来。生成式人工智能(AIGC)给传媒行业发展带来严峻挑战的同时&#xff0c;也带来千载难逢的重大发展机遇。2024年政府工作报告中提出&#xff0c;要深化大数据、人工智能等研发应用&#xff0c;开展“人工智能”行动&#xff0c;打造具有国际…

俚语加密漫谈

俚语加密是一种古老而有效的通信方式&#xff0c;将特定词语或短语在群体内赋予特殊含义&#xff0c;从而隐藏真实信息。类似于方言&#xff0c;它在历史上的应用不可忽视。随着计算机时代的到来&#xff0c;现代密码学通过数学运算编织密语&#xff0c;使得加密变得更加高深莫…

【win10 win11添加右键】git bash

打开注册表编辑器。 按下Win键 R&#xff0c;然后输入”regedit”并按下回车键来打开注册表编辑器。计算机\HKEY_CLASSES_ROOT\Directory\Background\shell\git_bash\command2. 导航到注册表路径&#xff1a;依次展开”HKEY_CLASSES_ROOT\Directory\Background\shell”。右键…

【数据结构】 HashMap源码分析(常量+构造方法+方法)

文章目录 HashMap源码分析一、成员常量二、构造方法三、方法1.此时假定为进行了无参构造&#xff0c;没有分配内存2.当发生有参构造时&#xff0c;完成对容量的大小判断后&#xff0c;将容量大小&#xff0c;传进tableSizeFor方法中&#xff1a; HashMap源码分析 一、成员常量…

iptables笔记

简介&#xff1a; iptables的前身叫ipfirewall &#xff08;内核1.x时代&#xff0c;当内核发展到2.x系列的时候&#xff0c;软件更名为ipchains&#xff0c;现在更名iptables&#xff0c;可以将规则组成一个列表&#xff0c;实现绝对详细的访问控制功能。 工作在用户空间中&…

如何使用Docker轻松构建和管理应用程序(二)

上一篇文章介绍了 Docker 基本概念&#xff0c;其中镜像、容器和 Dockerfile 。我们使用 Dockerfile 定义镜像&#xff0c;依赖镜像来运行容器&#xff0c;因此 Dockerfile 是镜像和容器的关键&#xff0c;Dockerfile 可以非常容易的定义镜像内容&#xff0c;同时在我们后期的微…

JDK8中ArrayList扩容机制

前言 这是基于JDK8的源码分析&#xff0c;在JDK6之前以及JDK11之后细节均有变动&#xff01;&#xff01; 首先来看ArrayList的构造方法 public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Seriali…

VUE3——Proxy API 与VUE2——defineProperty API区别

一、Object.defineProperty 定义&#xff1a;Object.defineProperty() 方法会直接在一个对象上定义一个新属性&#xff0c;或者修改一个对象的现有属性&#xff0c;并返回此对象 为什么能实现响应式 通过defineProperty 两个属性&#xff0c;get及set get 属性的 getter 函…

LeetCode刷题---查询近30天活跃用户数

1.给出满足的条件&#xff0c;截止至2019-07-27的近30天 activity_date BETWEEN DATE_ADD(2019-07-27,INTERVAL -29 day) and 2019-07-27这里使用了Between and 函数和 Date_add函数 2.按照日期分组&#xff0c;统计活跃用户个数 select activity_date day,count(distinct(us…

Python学习之-基础语法

第1关&#xff1a;行与缩进 任务描述 本关任务&#xff1a;改正代码中不正确的缩进&#xff0c;使其能够正常编译&#xff0c;并输出正确的结果。 编程要求 根据提示&#xff0c;改正右侧编辑器中代码的缩进错误&#xff0c;使其能够正确运行&#xff0c;并输出结果。 测试说明…

AcWing 1215. 小朋友排队 (树状数组)

n n n 个小朋友站成一排。 现在要把他们按身高从低到高的顺序排列&#xff0c;但是每次只能交换位置相邻的两个小朋友。 每个小朋友都有一个不高兴的程度。 开始的时候&#xff0c;所有小朋友的不高兴程度都是 0 0 0。 如果某个小朋友第一次被要求交换&#xff0c;则他的不…

蓝桥杯的数论总结

声明 我只是把数论相关的东西放在了一起&#xff0c;会有自己的理解&#xff0c;所以会有错误哈&#xff0c;欢迎在评论区中指出&#xff0c;另外有啥看不懂的也可以在评论区留言&#xff0c;我看到后就回你 质数 暴力 质数一般都是奇数&#xff0c;除了2小于2的不用考虑了…

Elasticsearch优化

集群配置 1、调整副本数&#xff1a;考虑数据的可用性和读取性能&#xff0c;合理配置分片的副本数。 2、合理配置分片大小(分片的合理容量&#xff1a;10GB-50GB)&#xff1a;避免分片过大&#xff0c;以确保更好的性能和均衡的负载。 3、监控集群状态&#xff1a;使用监控工…

mysql服务

任务描述:请安装mysql服务,建立数据表。 配置linux2为mysql服务器,创建数据库用户xiao,在任意机器上对所有数据库有完全权限。 创建数据库userdb;在库中创建表userinfo,表结构如下: 字段名 数据类型 主键

vue3+threejs新手从零开发卡牌游戏(十六):初始化对方手牌

添加对方手牌区时注意位置调整&#xff0c;以及手牌应该是背面朝上&#xff0c;加个rotateX翻转即可&#xff0c;其他代码和p1.vue代码一致&#xff0c;game/hand/p2.vue代码如下&#xff1a; <template><div></div> </template><script setup lan…

STL的基本概念

一、STL的诞生 长久以来&#xff0c;软件界一直希望建立一种可重复利用的东西 C的面向对象和泛型编程思想&#xff0c;目的就是复用性的提升 面向对象的三大特性(简单理解) 封装&#xff1a;把属性和行为抽象出来作为一个整体来实现事和物 继承&#xff1a;子类继承父类&a…

目前可用的免费云服务器整理汇总

随着云计算技术的飞速发展&#xff0c;越来越多的企业和个人开始关注并使用云服务器。为了吸引用户上云&#xff0c;各大云服务商纷纷推出了免费云服务器&#xff0c;供用户免费试用。本文将为大家整理汇总目前市场上可用的免费云服务器&#xff0c;以便大家更好地选择适合自己…

GIS与Python机器学习:开创地质灾害风险评价新纪元

地质灾害是指全球地壳自然地质演化过程中&#xff0c;由于地球内动力、外动力或者人为地质动力作用下导致的自然地质和人类的自然灾害突发事件。由于降水、地震等自然作用下&#xff0c;地质灾害在世界范围内频繁发生。我国除滑坡灾害外&#xff0c;还包括崩塌、泥石流、地面沉…

Verilog语言中parameter、localparam和符号常量的深度解析

1.parameter常量&#xff08;符号常量&#xff09; 用parameter来定义一个标示符&#xff0c;代表一个常量&#xff0c;称为符号常量 格式&#xff1a;parameter 参数名1 表达式&#xff0c; 参数名2 表达式&#xff1b;parameter 参数型数据的确认符&#xff0c;后边的为赋…