首页 > 编程语言 >服务端开发模式-thinkphp-重新整理workman

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

时间:2025-01-15 20:31:12浏览次数:3  
标签:workman resData param 重新整理 token time thinkphp data id

一、登录接口

<?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));//解密 --转换token
            if(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项目开发文档中有些问题。所以今天与明后天彻底解决一下这个问题。请谅解。

标签:workman,resData,param,重新整理,token,time,thinkphp,data,id
From: https://blog.csdn.net/m0_63603104/article/details/145149550

相关文章

  • 接口项目uuid算法开发及验证-thinkphp6-rabbitmq
    一、uuid算法开发if(!function_exists('uuid')){/***生成uuid*User:龙哥·三年风水*Date:2024/6/7*Time:11:08*@paramstring$prefix*@returnstring*/functionuuid($prefix=''){$s=......
  • ThinkPHP5框架下解决路径配置错误导致模板无法找到的问题
    问题描述:在使用ThinkPHP5开发Web应用程序时,有时会遇到因为路径设置不当而导致试图加载的视图文件不存在的情况。面对这样的报错提示,我们应该怎样排查并修复呢?解决方案:确认项目目录结构:检查项目的物理文件夹组织方式是否与预期一致,特别是application目录下的控制器、模型、视图......
  • 如何在Windows IIS 7.5或以上版本中配置ThinkPHP的伪静态规则?
    请将以下代码另存为web.config文件,注意后缀是.config,可以先保存在记事本中,重命名,然后上传到网站根目录中,即可生效。<?xmlversion="1.0"encoding="UTF-8"?><configuration><system.webServer><rewrite><rules>&l......
  • 如何在 Windows IIS 7.5 或以上版本中配置 ThinkPHP 的伪静态规则?
    URL优化是提升用户体验和搜索引擎友好性的重要手段。ThinkPHP框架以其简洁高效的路由机制深受开发者喜爱,但在WindowsIIS7.5或更高版本的服务器环境中,正确配置伪静态规则对于实现URL优化至关重要。以下是详细的配置步骤:配置步骤创建 web.config 文件打开文本编辑器......
  • 【thinkphp】国密sm2
    一、下载  lpilp/guomi依赖composerrequirelpilp/guomi二、使用lpilp/guomi<?phpnamespaceapp\controller;useRtgm\sm\RtSm2;useRtgm\sm\RtSm3;classSm{protected$privateKey=null;protected$publicKey=null;publicfunction__cons......
  • Thinkphp-Laravel中国通史介绍历史网站设计与制作
    目录课题介绍具体实现截图课程项目技术路线代码流程执行分析thinkphp框架解析开发技术介绍PHP核心代码部分展示详细视频演示源码获取课题介绍实现了一个完整的中国通史介绍网站系统,其中主要有用户模块、用户表模块、图说历史模块、关于我们模块、收藏表模块、搜索发......
  • thinkphp8:创建thinkphp项目(thinkphp v8.1.1)
    一,用composer创建项目$composercreate-projecttopthink/thinkgsadm查看的项目版本:$phpthinkversionv8.1.1二,配置nginx访问thinkphp项目server{listen8090;root/data/thinkphp/gsadm/public;server_nametpapibase;i......
  • Thinkphp 使用workerman消息实现消息推送完整示例
    1.版本说明:ThinkPHP6.0+、PHP8.0+2.实现原理    应用场景,监听用户登陆,修改用户登陆状态,通过心跳时间计算用户是否下线,其他应用场景自行修改逻辑即可。第一步:安装workermancomposerrequiretopthink/think-worker第二步:修改配置文件//执行以上代码后,config目录......
  • thinkphp 自定义命令生成验证器文件
    命令demo phpthinkhello(指令)--table表名代码如下<?phpdeclare(strict_types=1);namespaceapp\command;useDateTime;usethink\console\Command;usethink\console\Input;usethink\console\input\Option;usethink\console\Output;usethink\fa......
  • 【2024最新黑客工具分享】TPscan - 一键ThinkPHP漏洞检测getshell
    0x00工具介绍TPscan是一款基于Python3的ThinkPHP漏洞检测工具。0x01下载链接TPscan下载链接:夸克网盘分享0x02功能介绍thinkphp_checkcode_time_sqli_verifythinkphp_construct_code_exec_verifythinkphp_construct_debug_rce_verifythinkphp_debug_index_......