服务端开发模式-thinkphp-重新整理workman

一、登录接口
<?php
/*** 登录退出操作* User: 龙哥·三年风水* Date: 2024/10/29* Time: 15:53*/
namespace app\controller\common;
use app\controller\Emptys;
use app\model\permission\Admin;
use app\model\param\System as SystemModel;
use Email\EmailSender;
use Other\Browser;
use Redis\Redis;
use app\model\common\Token as TokenModel;
use Encipher\Encrypt;
use Workman\GatewayWork;class Login extends Emptys
{//验证码展示public function getCode(){$re = app()->make(\Other\Captcha::class)->create();$base64 = 'data:image/png;base64,' . base64_encode($re->getData());return succ('SUCCESS',$base64);}//登录public function doLogin(){$param = $this->request->param();$validate = new \app\validate\common\Login;$result = $validate->check($param);//参数验证if (!$result) return err($validate->getError());//验证码的正确性if (!app()->make(\Other\Captcha::class)->check($param['captcha_code'])) return err('验证码错误');//if (time() + 5 < strtotime($param['login_time'])) return err('非法登录');$resData = Admin::dataFind(['email' => trim($param['username'])], 'id,realname,password,ip,status', true);//用户信息的正确性if (empty($resData) && empty($resData['id'])) return err('用户不存在');if ($resData['status'] !== 1) return err('该账号已被禁用');$systemParam = SystemModel::dataFind(['id' => 1],'security_password,platform_token_expira');if ($resData['password'] !== sha1($param['password'] . $systemParam['security_password'])) return err('账号对应的密码错误');$loginIp = $this->request->header('x-real-ip');if(!empty($resData['ip'])){if($resData['ip'] != $loginIp)return err('禁止访问,不在IP白名单中');}// 获取浏览器版本$browserId = Browser::getVersion();// 获取该用户是否在登录状态下$tokenId = Redis::select(config('cache.stores.redis.token_db'))->get('token_' . $resData['id']);// 如果在登录状态下,需要确认IP是否一致if(!empty($tokenId)){$tokenValue = explode('|', Encrypt::decryptRsa($tokenId));//解密 --转换tokenif(count($tokenValue) > 0){$tokenSelect = count($tokenValue) == 2 ? sha1(sha1($tokenValue[0]).strtotime($tokenValue[1])) : $tokenValue[0];// 读取用户之前登录的IP及浏览器$resTokenLogin = TokenModel::dataFind(['token' => $tokenSelect,'token_type' => 1],'id,random_number,browser_id,login_ip',true);// 如果之前登录的IP存在 之前登录的IP与现在登录的IP进行对比if(!empty($resTokenLogin)){// 如果不相等的情况下,需要告知之前的浏览器做退出动作if($loginIp != $resTokenLogin['login_ip']){TokenModel::save(['expire_time' => time()], ['token' => $tokenSelect]);$this->setToken(3,'PermissionMemberLogout',$resData['id'],$resTokenLogin['random_number'],$resTokenLogin['browser_id'],$resTokenLogin['login_ip'],$tokenSelect);Redis::select(config('cache.stores.redis.token_db'))->del('token_' . $tokenSelect);GatewayWork::onRepeatClose($resData['id']);}else{// 如果相等的情况下,就需要判断浏览器是否相等啦,如果不相等的情况下,也是需要让之前的账号多退出的动作if($browserId == $resTokenLogin['browser_id'])return err('已登录,不可再次登录');if($browserId != $resTokenLogin['browser_id']){TokenModel::save(['expire_time' => time()], ['token' => $tokenSelect]);$this->setToken(3,'PermissionMemberLogout',$resData['id'],$resTokenLogin['random_number'],$resTokenLogin['browser_id'],$resTokenLogin['login_ip'],$tokenSelect);Redis::select(config('cache.stores.redis.token_db'))->del('token_' . $tokenSelect);GatewayWork::onRepeatClose($resData['id']);}}}}}//写入Token日志$dataRandomNumber = alnum();$expireTime = strtotime($param['login_time']) + $systemParam['platform_token_expira'];$token = $resData['id'].$dataRandomNumber;$dataToken = sha1( sha1($token). strtotime($param['login_time']));$this->setToken(1,'CommonLoginDoLogin',$resData['id'],$dataRandomNumber,$browserId,$loginIp,$dataToken,$expireTime);//加入跨站攻击验证队列Redis::select(config('cache.stores.redis.token_db'))->setex('token_' . $dataToken,$systemParam['platform_token_expira'],$resData['id']);Redis::select(config('cache.stores.redis.token_db'))->setex('token_' . $resData['id'],$systemParam['platform_token_expira'],Encrypt::encryptRsa($dataToken));/*$emailSender = new EmailSender();$emailSender::send($param['username'],'登录系统',$resData['realname'].'于'.$param['login_time'].'登录系统');*/return succ('登录成功',Encrypt::encryptRsa($token));}/*** 操作日志记录* User: 龙哥·三年风水* Date: 2024/12/12* Time: 17:11* @ param $tokenType 操作类型* @ param $menuName 权限名称*/private function setToken($tokenType,$menuName,$adminId,$randomNumber,$browserId,$loginIp,$token,$expireTime = ''){$data['token_type'] = $tokenType;$data['menu_name'] = $menuName;$data['admin_id'] = $adminId;$data['random_number'] = $randomNumber;$data['browser_id'] = $browserId;$data['login_ip'] = $loginIp;$data['create_time'] = date('Y-m-d',time());$data['login_time'] = date('Y-m-d H:i:s',time());$data['expire_time'] = empty($expireTime) ? time() : $expireTime;$data['token'] = $token;TokenModel::save($data,[]);}
}
二、长链接封装
<?php
/*** 长链接发送信息* User: 龙哥 三年风水* Date: 2024/12/21/0021* Time: 22:52*/
namespace Workman;
use GatewayClient\Gateway;
class GatewayWork
{//向客户端发送内容public static function sendToClient($client_id, $data){//获取配置文件$isFormal = config('socket.is_formal');Gateway::$registerAddress = config("socket.tcp_address.{$isFormal}.address");Gateway::sendToClient($client_id, $data);}//向群推送数据public static function sendToGroup($group,$message){//获取配置文件$isFormal = config('socket.is_formal');Gateway::$registerAddress = config("socket.tcp_address.{$isFormal}.address");Gateway::sendToGroup($group,json_encode($message));}//批量向客户端发送内容public static function sendToAll($message, $client_id_array = null){//获取配置文件$isFormal = config('socket.is_formal');Gateway::$registerAddress = config("socket.tcp_address.{$isFormal}.address");Gateway::sendToAll(json_encode($message), $client_id_array);}//获取与 uid 绑定的 client_id 列表public static function getClientIdByUid($uid){//获取配置文件$isFormal = config('socket.is_formal');Gateway::$registerAddress = config("socket.tcp_address.{$isFormal}.address");return Gateway::getClientIdByUid($uid);}//重复登录关闭客户端public static function onRepeatClose($userId){//获取配置文件$isFormal = config('socket.is_formal');Gateway::$registerAddress = config("socket.tcp_address.{$isFormal}.address");$resUser = Gateway::isUidOnline((int)$userId);if($resUser == 1){$resClientUser = Gateway::getClientIdByUid((int)$userId);foreach ($resClientUser as $v){Gateway::sendToClient($v, json_encode(['type' => 'repeat_close','data' => 'ok']));Gateway::destoryClient($v);}}}//正常退出关闭客户端public static function onArtificialClose($userId){//获取配置文件$isFormal = config('socket.is_formal');Gateway::$registerAddress = config("socket.tcp_address.{$isFormal}.address");$resUser = Gateway::isUidOnline((int)$userId);if($resUser == 1){$resClientUser = Gateway::getClientIdByUid((int)$userId);foreach ($resClientUser as $v){Gateway::sendToClient($v, json_encode(['type' => 'artificial_close','data' => 'ok']));Gateway::destoryClient($v);}}}//到期退出关闭客户端public static function onExpireClose($userId){//获取配置文件$isFormal = config('socket.is_formal');Gateway::$registerAddress = config("socket.tcp_address.{$isFormal}.address");$resUser = Gateway::isUidOnline((int)$userId);if($resUser == 1){$resClientUser = Gateway::getClientIdByUid((int)$userId);foreach ($resClientUser as $v){Gateway::sendToClient($v, json_encode(['type' => 'expire_close','data' => 'ok']));Gateway::destoryClient($v);}}}
}
三、提前说明
因最近一段时间比较忙,导致精力不能集中。之前封装的vue-element-admin与thinkphp6追加长链接workman项目开发文档中有些问题。所以今天与明后天彻底解决一下这个问题。请谅解。
相关文章:
服务端开发模式-thinkphp-重新整理workman
一、登录接口 <?php /*** 登录退出操作* User: 龙哥三年风水* Date: 2024/10/29* Time: 15:53*/ namespace app\controller\common; use app\controller\Emptys; use app\model\permission\Admin; use app\model\param\System as SystemModel; use Email\EmailSender; use…...
HTB:Access[WriteUP]
目录 连接至HTB服务器并启动靶机 信息收集 使用rustscan对靶机TCP端口进行开放扫描 将靶机TCP开放端口号提取并保存 使用nmap对靶机TCP开放端口进行脚本、服务扫描 使用nmap对靶机TCP开放端口进行漏洞、系统扫描 使用nmap对靶机常用UDP端口进行开放扫描 尝试匿名连接至…...
【论文笔记】SmileSplat:稀疏视角+pose-free+泛化
还是一篇基于dust3r的稀疏视角重建工作,作者联合优化了相机内外参与GS模型,实验结果表明优于noposplat。 abstract 在本文中,提出了一种新颖的可泛化高斯方法 SmileSplat,可以对无约束(未标定相机的)稀疏多…...
电机控制的数字化升级:基于DSP和FPGA的仿真与实现
数字信号处理器(DSP,Digital Signal Processor)在工业自动化领域的应用日益广泛。DSP是一种专门用于将模拟信号转换成数字信号并进行处理的技术,能够实现信号的数字滤波、重构、调制和解调等多项功能,确保信号处理的精…...
1/14 C++
练习:将图形类的获取周长和获取面积函数设置成虚函数,完成多态 再定义一个全局函数,能够在该函数中实现:无论传递任何图形,都可以输出传递的图形的周长和面积 #include <iostream>using namespace std; class Sh…...
java springboot3.x jwt+spring security6.x实现用户登录认证
springboot3.x jwtspring security6.x实现用户登录认证 什么是JWT JWT(JSON Web Token)是一种开放标准(RFC 7519),它用于在网络应用环境中传递声明。通常,JWT用于身份验证和信息交换。JWT的一个典型用法是…...
YOLOv5训练长方形图像详解
文章目录 YOLOv5训练长方形图像详解一、引言二、数据集准备1、创建文件夹结构2、标注图像3、生成标注文件 三、配置文件1、创建数据集配置文件2、选择模型配置文件 四、训练模型1、修改训练参数2、开始训练 五、使用示例1、测试模型2、评估模型 六、总结 YOLOv5训练长方形图像详…...
【2025最新】Poe保姆级订阅指南,Poe订阅看这一篇就够了!最方便使用各类AI!
1.Poe是什么? Poe, 全称Platform for Open Exploration。 Poe本身并不提供基础的大语言模型,而是整合多个来自不同科技巨头的基于不同模型的AI聊天机器人,其中包括来自OpenAI的ChatGPT,Anthropic的Claude、Google的PaLM…...
type1-100,2 words
dish n.餐具、碟,盘子;菜肴、饭菜(指一顿餐食中的一道菜) kind of 稍微;有点 sort of 稍微;有点儿 smallish adj.有点小的 crack 敲碎/裂,敲开,砸开,砸碎;裂开…...
Leetcode 377. 组合总和 Ⅳ 动态规划
原题链接:Leetcode 377. 组合总和 Ⅳ 可参考官解 class Solution { public:int combinationSum4(vector<int>& nums, int target) {vector<int> dp(target 1);dp[0] 1;// 总和为 i 的元素组合的个数for (int i 1; i < target; i) {// 每次都…...
计算机网络(五)——传输层
一、功能 传输层的主要功能是向两台主机进程之间的通信提供通用的数据传输服务。功能包括实现端到端的通信、多路复用和多路分用、差错控制、流量控制等。 复用:多个应用进程可以通过同一个传输层发送数据。 分用:传输层在接收数据后可以将这些数据正确分…...
【SQL】进阶知识 -- 删除表的几种方法(包含表内单个字段的删除方法)
大家好!欢迎来到本篇SQL进阶博客。如果你已经掌握了基础的SQL操作,接下来就让我们一起探索删除表的几种方法。删除表可能听起来有点危险,事实也是如此,所以在我们实际开发过程中,大多数时候我们都有数据的使用权限&…...
【搭建JavaEE】(3)前后端交互,请求响应机制,JDBC数据库连接
前后端交互 Apache Tomat B/S目前主流。 tomat包含2部分: apache容器 再认识servlet 抽象出的开发模式 项目创建配置 maven javaeetomcat 忽略一些不用的文件 webapp文件夹 HiServlet 这里面出现了webinfo,这个别删因为这个呢,是这这个这…...
项目概述、开发环境搭建(day01)
软件开发整体介绍 软件开发流程 第1阶段: 需求分析 需求规格说明书, 一般来说就是使用 Word 文档来描述当前项目的各个组成部分,如:系统定义、应用环境、功能规格、性能需求等,都会在文档中描述。产品原型,一般是通过…...
车联网安全--TLS握手过程详解
目录 1. TLS协议概述 2. 为什么要握手 2.1 Hello 2.2 协商 2.3 同意 3.总共握了几次手? 1. TLS协议概述 车内各ECU间基于CAN的安全通讯--SecOC,想必现目前多数通信工程师们都已经搞的差不多了(不要再问FvM了);…...
【python】OpenCV—Extract Horizontal and Vertical Lines—Morphology
文章目录 1、功能描述2、代码实现3、效果展示4、完整代码5、参考 更多有趣的代码示例,可参考【Programming】 1、功能描述 基于 opencv-python 库,利用形态学的腐蚀和膨胀,提取图片中的水平或者竖直线条 2、代码实现 导入基本的库函数 im…...
Redis十大数据类型详解
Redis(一) 十大数据类型 redis字符串(String) string是redis最基本的类型,一个key对应一个value string类型是二进制安全的,意思是redis的string可以包含任何数据。例如说是jpg图片或者序列化对象 一个re…...
Open FPV VTX开源之betaflight配置
Open FPV VTX开源之betaflight配置 1. 源由2. 配置3. 总结4. 参考资料5. 补充 - 飞控固件版本 1. 源由 飞控嵌入式OSD - ardupilot配置使用betaflight配套OSD图片。 Choose correct font depending on Flight Controller SW. ──> /usr/share/fonts/├──> font_btfl…...
AT32 bootloader程序与上位机程序
从8051到stm32, 从串口下载到JLINK调试,从keil到arm-none-eabi-gcc,从"Hello wrold"到通信协议,一路起来已学会很多,是时候写一下bootloader了。 基本原理 单片机代码编译完后可以生成".hex"和".bin"文件&…...
数据结构与算法之栈: LeetCode 151. 反转字符串中的单词 (Ts版)
反转字符串中的单词 https://leetcode.cn/problems/reverse-words-in-a-string/ 描述 给你一个字符串 s ,请你反转字符串中 单词 的顺序单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开 返回 单词 顺序颠倒且 单词 之间用单个空…...
PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...
华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !
我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...
Vue3中的computer和watch
computed的写法 在页面中 <div>{{ calcNumber }}</div>script中 写法1 常用 import { computed, ref } from vue; let price ref(100);const priceAdd () > { //函数方法 price 1price.value ; }//计算属性 let calcNumber computed(() > {return ${p…...
嵌入式面试常问问题
以下内容面向嵌入式/系统方向的初学者与面试备考者,全面梳理了以下几大板块,并在每个板块末尾列出常见的面试问答思路,帮助你既能夯实基础,又能应对面试挑战。 一、TCP/IP 协议 1.1 TCP/IP 五层模型概述 链路层(Link Layer) 包括网卡驱动、以太网、Wi‑Fi、PPP 等。负责…...
