群控系统服务端开发模式-应用开发-业务架构逻辑开发第一轮测试
整个系统的第一个层次已经开发完毕,已经有简单的中控,登录、退出、延迟登录时长、黑名单、数据层封装、验证层封装、RSA加解密、Redis等功能,还缺获取个人、角色按钮权限、角色菜单权限功能。角色按钮权限以及角色菜单权限等明后天开发,今天先开发个人信息接口以便测试使用。
一、个人信息接口开发
1、添加路由
在根目录下route文件夹中的app.php文件中加入以下代码:
Route::post('member/personal_data','permission.Member/personalData');
2、代码开发
在根目录下app文件夹下的controller文件夹中创建文件夹并命名为permission,然后在permission文件夹中创建控制器并命名为Member,然后在Member文件中继承Base总控制后并创建personalData方法。具体代码如下:
<?php
/*** 个人信息控制-也就是登录者信息及角色对外方法* User: 龙哥·三年风水* Date: 2024/10/30* Time: 14:18*/
namespace app\controller\permission;
use app\controller\Base;
class Member extends Base
{/*** 获取个人信息* User: 龙哥·三年风水* Date: 2024/10/30* Time: 14:23* @ return \think\response\Json*/public function personalData(){$data = [];$data['username'] = $this->username;$data['avatar'] = $this->avatar;$data['email'] = $this->email;$data['realname'] = $this->realname;return succ('操作成功',$data);}
}
二、nginx黑名单开发
因nginx自身是没有redis及rsa扩展使用的,所以我安装的不是nginx,而是openresty,他是有带resty扩展的。如果不会安装openresty,可以参照《centos7 二进制安装openresty》、《配置openresty》以及《openresty安全机制-白名单》三篇文章进行安装配置。
1、引入扩展
--引入Redis
local redis = require "resty.redis";
--引入rsa
local rsa = require "resty.rsa";
2、配置redis
--Redis链接ip
local ip = "172.20.36.144"
--Redis链接端口
local port = 6379
--Redis连接密码
local pass = "QXtr@@PxjoLenGon"
3、在对应的Redis库里面添加公钥字符串
我不管是在应用程序里面还是在本机制里面,都采用的是Redis第0号库的black-list库中哈,所有的非正常访问系统的IP都在black-list库中。
4、开发lua对应的Redis授权
--鉴权Redis
local function connAuth()local red = redis:new();local connCount, err = red:connect(ip, port);if not connCount thenngx.say("failed to connect: ", err)close_redis(red)returnendred:set_timeouts(2000);local ok, err = red:auth(pass)if not ok thenngx.say("failed to auth: ", err)close_redis(red)returnendreturn red
end
5、开发lua对应的Redis关闭
--关闭Redis
local function close_redis(red)if not red thenreturnend--释放连接(连接池实现)local pool_max_idle_time = 10000local pool_size = 100local ok, err = red:set_keepalive(pool_max_idle_time, pool_size)if not ok thenngx.say("set keepalive error : ", err)end
end
6、开发获取请求者IP
--获取请求者IP
local function getIp()local clientIP = ngx.req.get_headers()["X-Real-IP"]if clientIP == nil thenclientIP = ngx.req.get_headers()["x_forwarded_for"]endif clientIP == nil thenclientIP = ngx.var.remote_addrendreturn clientIP
end
--获取用户访问IP
local clientIP = getIp();
--封禁token时间(秒)
local token_block_time= 120
--指定token访问频率计数最大值(次)
local token_max_count = 3
7、开发空方法
--如果数据为空的情况下
local function is_empty(value)if type(value) == "table" thenreturn next(value) == nilelseif type(value) == "string" thenreturn #value == 0elseif type(value) == "nil" thenreturn trueendreturn false
end
8、过滤特殊字符串
--过滤特殊字符串(只保留字母与数字,字母不区分大小写)
local function filter_special_chars(s)local ss = {}local k = 1while true doif k > #s then break endlocal c = string.byte(s,k)if not c then break endif c<192 thenif (c>=48 and c<=57) or (c>= 65 and c<=90) or (c>=97 and c<=122) thentable.insert(ss, string.char(c))endk = k + 1endendreturn table.concat(ss)
end
9、组合开发黑名单机制
--引入Redis
local redis = require "resty.redis";
--引入rsa
local rsa = require "resty.rsa";
--Redis链接ip
local ip = "172.20.36.144"
--Redis链接端口
local port = 6379
--Redis连接密码
local pass = "QXtr@@PxjoLenGon"
--鉴权Redis
local function connAuth()local red = redis:new();local connCount, err = red:connect(ip, port);if not connCount thenngx.say("failed to connect: ", err)close_redis(red)returnendred:set_timeouts(2000);local ok, err = red:auth(pass)if not ok thenngx.say("failed to auth: ", err)close_redis(red)returnendreturn red
end--关闭Redis
local function close_redis(red)if not red thenreturnend--释放连接(连接池实现)local pool_max_idle_time = 10000local pool_size = 100local ok, err = red:set_keepalive(pool_max_idle_time, pool_size)if not ok thenngx.say("set keepalive error : ", err)end
end--获取请求者IP
local function getIp()local clientIP = ngx.req.get_headers()["X-Real-IP"]if clientIP == nil thenclientIP = ngx.req.get_headers()["x_forwarded_for"]endif clientIP == nil thenclientIP = ngx.var.remote_addrendreturn clientIP
end
--获取用户访问IP
local clientIP = getIp();
--封禁token时间(秒)
local token_block_time= 120
--指定token访问频率计数最大值(次)
local token_max_count = 3--如果数据为空的情况下
local function is_empty(value)if type(value) == "table" thenreturn next(value) == nilelseif type(value) == "string" thenreturn #value == 0elseif type(value) == "nil" thenreturn trueendreturn false
end--过滤特殊字符串(只保留字母与数字,字母不区分大小写)
local function filter_special_chars(s)local ss = {}local k = 1while true doif k > #s then break endlocal c = string.byte(s,k)if not c then break endif c<192 thenif (c>=48 and c<=57) or (c>= 65 and c<=90) or (c>=97 and c<=122) thentable.insert(ss, string.char(c))endk = k + 1endendreturn table.concat(ss)
end--如果头部信息没有指定的参数或是指定参数的值无法解析,加入IP黑名单
--如果同样的头部参数键在封禁token时间内连续访问指定token访问频率计数最大值次以上,加入IP黑名单----暂时还没有开发,开发测试好后,将重新更新
local function set_blacklist()local header = ngx.req.get_headers();local red = connAuth();local token, err = header["Authorization"];-- 如果参数为空的情况下if not token thenlocal res, err = red:sismember('black-list', clientIP);if res ~= 1 thenred:sadd('black-list', clientIP)endclose_redis(red)return ngx.exit(401)else-- 如果参数值为空的情况下if is_empty(token) thenlocal res, err = red:sismember('black-list', clientIP);if res ~= 1 thenred:sadd('black-list', clientIP)endclose_redis(red)return ngx.exit(401)end-- 如果参数值采用base64解析不开的情况下local encrypted, err = tostring(ngx.decode_base64(token))if not encrypted thenlocal res, err = red:sismember('black-list', clientIP);if res ~= 1 thenred:sadd('black-list', clientIP)endclose_redis(red)return ngx.exit(401)end-- 采用rsa技术解析token base64过后的值内容local priv_key = '-----BEGIN PRIVATE KEY-----\n' ..red:get('priv_key_cluster_control')..'\n-----END PRIVATE KEY-----';local priv, err = rsa:new({private_key = priv_key})local dst, err = rsa.decrypt(priv, encrypted)if not dst thenlocal res, err = red:sismember('black-list', clientIP);if res ~= 1 thenred:sadd('black-list', clientIP)endclose_redis(red)return ngx.exit(401)endend
end-- 查看是否在黑名单里面
local function get_blacklist()local red = connAuth();local res, err = red:sismember('black-list', clientIP);if res == 1 thenclose_redis(red);return ngx.exit(401);endclose_redis(red);
endget_blacklist();
set_blacklist();
10、将开发好的lua文件也一并上传到网站目录中,然后更改nginx应用配置文件,然后重新启动nginx,代码如下:
server {listen 80;server_name controlapi.yuanlongsoftware.cn;error_log /data/nginx/controlapi.yuanlongsoftware.cn80_error.log crit;access_log /data/nginx/controlapi.yuanlongsoftware.cn80_acess_$logdate.log access-upstream;lua_code_cache off;autoindex off;server_tokens off;error_page 401 /401.html;location / {if ($request_method ~* OPTIONS) {return 200;}access_by_lua_file /data/wwwroot/teach/group_control/cluster_control/rsa-cluster-control.lua;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;add_header 'Access-Control-Allow-Credentials' 'true';add_header Access-Control-Allow-Origin "$http_origin";add_header Access-Control-Allow-Headers 'X-Requested-With,Cache-Control,Content-Type,Authorization';add_header Cache-Control no-cache;add_header 'Access-Control-Allow-Methods' 'GET, POST';proxy_pass http://controlapi;}location = /401.html {root "/data/wwwroot/error";}
}
三、测试
1、登录后用token去获取一下用户信息接口,采用apipost工具测试

2、采用同一个token再次去获取一下用户信息接口,采用apipost工具再次测试

3、采用同一个token再次去获取一下用户信息接口,采用apipost工具再次测试

第二次以后,就是openresty直接返回咯,因lua去检测是发现他就在黑名单中,就直接返回。
其实后期我还会出对应的精简文章,也就是优化过后的文章。
四、提前说明
明后天将带来管理员功能开发、角色功能开发、菜单功能开发以及上传文件开发
相关文章:
群控系统服务端开发模式-应用开发-业务架构逻辑开发第一轮测试
整个系统的第一个层次已经开发完毕,已经有简单的中控,登录、退出、延迟登录时长、黑名单、数据层封装、验证层封装、RSA加解密、Redis等功能,还缺获取个人、角色按钮权限、角色菜单权限功能。角色按钮权限以及角色菜单权限等明后天开发&#…...
git 怎么保留某个文件夹忽略其下面的所有文件?
在 Git 中,如果你想要保留某个文件夹(比如 folder/)但忽略其下面的所有文件,可以使用 .gitignore 文件来实现。需要注意的是,Git 不会自动创建空目录。因此,为了让 Git 记录这个空目录,你需要在…...
Linux Shell 实现一键部署mariadb11.6
mariadb MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可 MariaDB的目的是完全兼容MySQL,包括API和命令行,使之能轻松成为MySQL的代替品。在存储引擎方面,使用XtraDB来代替MySQL的InnoDB。 MariaDB由MySQL的创始人Michael Widenius主导开发…...
Servlet 3.0 注解开发
文章目录 Servlet3.0注解开发修改idea创建注解的servlet模板内容讲解 关于servlet3.0注解开发的疑问_配置路径省略了属性urlPatterns内容讲解内容小结 Servlet3.0注解开发 【1】问题 说明:之前我们都是使用web.xml进行servlet映射路径的配置。这样配置的弊端&…...
rom定制系列------红米note8_miui14安卓13定制修改固件 带面具root权限 刷写以及界面预览
💝💝💝红米note8机型代码:ginkgo。高通芯片。此固件官方最终版为稳定版12.5.5安卓11的版本。目前很多工作室需要高安卓版本的固件来适应他们的软件。并且需要root权限。根据客户要求。修改固件为完全root。并且修改为可批量刷写的…...
Kaspa钱包ts代码封装
文章目录 1. 配置wasm2. 钱包地址创建3. KAS转账&余额查询4. KRC-20 处理5. 使用demo 1. 配置wasm 下载wasm地址:https://kaspa.aspectron.org/nightly/downloads/ 在项目根目录下添加wasm目录, 将下载的wasm文件中web目录下kaspa和kaspa-dev文件家…...
MySQL 数据库中 MyISAM 和 InnoDB 的区别:深入解析
MySQL 是目前最流行的开源数据库管理系统之一,支持多种存储引擎,其中最常用的就是 MyISAM 和 InnoDB。这两种存储引擎各有其特点,适用于不同的使用场景。理解它们之间的区别有助于数据库开发者和管理者根据应用需求选择合适的存储引擎。本文将…...
python中怎样实现闭包?
在Python中,闭包是指一个函数可以访问其自身范围之外的变量,即可以访问其外部函数作用域中的变量。要实现一个闭包,可以按照以下步骤进行: 内部函数引用外部函数的变量:在外部函数中定义一个内部函数,并在…...
论文阅读:MultiUI 利用网页UI进行丰富文本的视觉理解
《HARNESSING WEBPAGE UIS FOR TEXT-RICH VISUAL UNDERSTANDING》 利用网页UI进行丰富文本的视觉理解 总结 grounding和QA部分的数据集占比较大、同时消融实验显示其作用相对较大,并且grounding部分作用和效果呈现scaling正相关提供了很多web数据处理成多模态训练…...
【云原生】云原生后端详解:架构与实践
目录 引言一、云原生后端的核心概念1.1 微服务架构1.2 容器化1.3 可编排性1.4 弹性和可伸缩性 二、云原生后端的架构示意图三、云原生后端的最佳实践3.1 使用服务网格3.2 监控与日志管理3.3 CI/CD 流水线3.4 安全性 总结参考资料 引言 随着云计算的迅猛发展,云原生…...
MySQL覆盖索引
覆盖索引(Covering Index)是数据库优化中的一种重要技术 覆盖索引是指一个查询语句在执行时,所需的数据可以完全通过索引来获取,而无需访问实际的数据行。也就是说,查询语句所需的列都包含在了创建的索引中,…...
「C/C++」C/C++ 之 循环结构详解
✨博客主页何曾参静谧的博客📌文章专栏「C/C」C/C程序设计📚全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…...
json-server的基本使用
一、json-server工具的使用 可以快速的搭建符合RESTful API服务。返回符合RESTful规范的数据; 1、全局引入json-server包 npm install -g json-server2、创建json格式的db.json文件 {"jsonData": [{"name": "小明"}] }3、在json文…...
华为配置BFD状态与接口状态联动实验
组网图形 图1 配置BFD状态与接口状态联动组网图 BFD简介配置注意事项组网需求配置思路操作步骤配置文件 BFD简介 为了减小设备故障对业务的影响,提高网络的可靠性,网络设备需要能够尽快检测到与相邻设备间的通信故障,以便及时采取措施&…...
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-22
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-22 目录 文章目录 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-22目录1. PoisonedRAG: Knowledge corruption attacks to retrieval-augmented generation of large language models摘要创新点…...
理解消息队列
消息队列(Message Queue)有下面四大作用: 解耦。几个业务系统之间可以通过 MQ 解耦,例如做数据同步数据的顺序性和可恢复性异步通讯缓冲能力 理解 MQ MQ 的前两个特点且不说,我们看看另外两个的。 异步通讯&#x…...
!什么,matlab也有网页版了
已经脱离matlab一下下几天的困境了,是的,matlab也有网页版了 附上网址: MATLAB Login | MATLAB & Simulink...
安卓屏幕息屏唤醒
背景,今天遇项目需要,需要在下载在后台任务运行时(如下载、上传或进行长时间计算),保持 CPU 活动,然后就写了这个实现方法,废话不多说上代码 第一步,再清单AndroidManifest文件声明权…...
类文件具有错误的版本 61.0, 应为 55.0
启动项目的时候报这个错误. 项目所使用的redis版本是jdk17的,而我使用的是Java11.所以要将redis版本降下来。 另一种方式就是修改jdk的版本,在设置修改编译版本,在版本控制里面修改jdk的版本。...
vue点击菜单,出现2个相同tab,啥原因
点击菜单,出现相同的tab 出现的原因: 1.组件中的name 和配置路由文件js, 的大小写不一致导致 2、跳转的路由整个地址,大小写不一致大致...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...
基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...
GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向
在人工智能技术呈指数级发展的当下,大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性,吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型,成为释放其巨大潜力的关键所在&…...
