前后分离式在用刷新TOKEN的大概方案

浏览:333 发布日期:2019/05/13 分类:技术分享
其实通过HEADER头部更新或者通过返回更新也是可以的,只是本人项目本来就在用socket.io所以使用了此方案
首先需要用到的是socket.io
https://www.workerman.net/web-sender 这是下载地址
为什么不用websocket的原因是IE兼容性不好,所以选择socket.io
更新部分代码<script src="https://cdn.bootcss.com/socket.io/2.0.3/socket.io.js"></script>
<script>
var host = "您的服务器IP:2120";      
var socketIo = io(host);
var userid = {uid:'123456'};
//链接服务器并发送登录用户
socketIo.on('connect', function(e){
    socketIo.emit('userLogin',userid );
});
//接收信息
socketIo.on('message', function(e){
     var data = JSON.parse(e);     
     if(data.type=="refreshToken"){
        //这里更新token 
        localStorage.setItem("token", data.token);
     }else if(data.type=="msg"){
        //这里还可以接收各种通知信息
        alert(data.msg);
     } 
});
</script>
将下载的socket服务端 修改 start_io.php文件<?php
use Workerman\Worker;
use Workerman\WebServer;
use Workerman\Lib\Timer;
use PHPSocketIO\SocketIO;

include __DIR__ . '/vendor/autoload.php';

// 全局数组保存uid在线数据
$uidConnectionMap = array();
//存链接用户有的SOCKET ID;
$uidToScokeid = array();
// 记录最后一次广播的在线用户数

$last_online_count = 0;
// 记录最后一次广播的在线页面数
$last_online_page_count = 0;

// PHPSocketIO服务
$sender_io = new SocketIO(2120);
// 客户端发起连接事件时,设置连接socket的各种事件回调
$sender_io->on('connection', function($socket){
    // 当客户端发来登录事件时触发
    $socket->on('login', function ($uid)use($socket){
        global $uidConnectionMap, $last_online_count, $last_online_page_count;
        // 已经登录过了
        if(isset($socket->uid)){
            return;
        }
        // 更新对应uid的在线数据
        $uid = (string)$uid;
        if(!isset($uidConnectionMap[$uid]))
        {
            $uidConnectionMap[$uid] = 0;
        }
        // 这个uid有++$uidConnectionMap[$uid]个socket连接
        ++$uidConnectionMap[$uid];
        // 将这个连接加入到uid分组,方便针对uid推送数据
        $socket->join($uid);
        $socket->uid = $uid;
        // 更新这个socket对应页面的在线数据        
    });
    //商户中心通知专用
      $socket->on('userLogin', function ($message)use($socket){
        global $uidConnectionMap, $uidToScokeid,$last_online_count, $last_online_page_count;        
        $uid = $message['uid'];
        //在这可以加些判断
          if($uid != 1){
            //非法用户可以直接断开链接
            echo "userNotify:".$message['uid']." no auth user".PHP_EOL;
              $socket->disconnect();
            return;
        }
        // 已经登录过了
        if(isset($socket->uid)){
              $socket->disconnect();
            return;
        }
        // 更新对应uid的在线数据
        $uid = (string)$uid;
        if(!isset($uidConnectionMap[$uid]))
        {
            $uidConnectionMap[$uid] = 0;
            $uidToScokeid[$uid] = $socket->id;
        }else{
            $socket->disconnect();
              return;
        }
        // 这个uid有++$uidConnectionMap[$uid]个socket连接
        ++$uidConnectionMap[$uid];
        // 将这个连接加入到uid分组,方便针对uid推送数据
        $socket->join("userLogin");
        $socket->uid = $uid;
    });
    
    // 当客户端断开连接是触发(一般是关闭网页或者跳转刷新导致)
    $socket->on('disconnect', function () use($socket) {
        if(!isset($socket->uid))
        {
             return;
        }
        global $uidConnectionMap, $sender_io;
        // 将uid的在线socket数减一
        if(--$uidConnectionMap[$socket->uid] <= 0)
        {
            unset($uidConnectionMap[$socket->uid]);
            unset($uidToScokeid[$socket->uid]);
        }
    });
});

// 当$sender_io启动后监听一个http端口,通过这个端口可以给任意uid或者所有uid推送数据
$sender_io->on('workerStart', function(){
    // 监听一个http端口
    $inner_http_worker = new Worker('http://0.0.0.0:2121');
    // 当http客户端发来数据时触发
    $inner_http_worker->onMessage = function($http_connection, $data){
        global $uidConnectionMap,$uidToScokeid;
        $_POST = $_POST ? $_POST : $_GET;
        // 推送数据的url格式 type=publish&to=uid&content=xxxx
        //判断数据是否为合法的来源做了简单的sign md5
        $sign = md5($postData['to']."send123456");
          if($sign != $postData['sign']){
            return;
        }
        switch($postData['type']){
            case 'publish':
                global $sender_io;
                $to = $postData['to'];
                
                // 有指定uid则向uid所在socket组发送数据
                if($to){
                      if(isset($uidToScokeid[$to])){
                          $sender_io->to($uidToScokeid[$to])->emit('message', $postData['content']);
                    }                    
                // 否则向所有uid推送数据
                }else{
                    $sender_io->emit('message', $postData['content']);
                }
                // http接口返回,如果用户离线socket返回fail
                if($to && !isset($uidConnectionMap[$to])){
                    return $http_connection->send('offline');
                }else{
                    return $http_connection->send('ok');
                }
        }
        return $http_connection->send('fail');
    };
    // 执行监听
    $inner_http_worker->listen();

    // 一个定时器,定时向所有uid推送当前uid在线数及在线页面数
    Timer::add(1, function(){
        global $uidConnectionMap, $sender_io, $last_online_count, $last_online_page_count;
        $online_count_now = count($uidConnectionMap);
        $online_page_count_now = array_sum($uidConnectionMap);
        // 只有在客户端在线数变化了才广播,减少不必要的客户端通讯
        if($last_online_count != $online_count_now || $last_online_page_count != $online_page_count_now)
        {
            $sender_io->emit('update_online_count', "当前<b>{$online_count_now}</b>人在线,共打开<b>{$online_page_count_now}</b>个页面");
            $last_online_count = $online_count_now;
            $last_online_page_count = $online_page_count_now;
        }
    });
});

if(!defined('GLOBAL_START'))
{
    Worker::runAll();
}
后端发送代码如发送ID为123456的用户
$msg = ["type"=>"refreshToken","token"=>"TOKEN值"];
sendSocketTo("123456",json_encode($msg));//在判断用户登录状态的时候判断下时间是否快要过期了,然后再发送
function sendSocketTo($to_uid,$message){
// 推送的url地址,使用自己的服务器地址
    $push_api_url = "http://您的服务器地址:2121/";
    $post_data = array(
        "type" => "publish",
        "content" => $message,
        "to" => $to_uid,
        'sign' => md5($to_uid."send123456")
    );
    $ch = curl_init ();
    curl_setopt ( $ch, CURLOPT_URL, $push_api_url );
    curl_setopt ( $ch, CURLOPT_POST, 1 );
    curl_setopt ( $ch, CURLOPT_HEADER, 0 );
    curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
    curl_setopt ( $ch, CURLOPT_POSTFIELDS, $post_data );
    curl_setopt ($ch, CURLOPT_HTTPHEADER, array("Expect:"));
    $return = curl_exec ( $ch );
    curl_close ( $ch );
    return $return;
}
以上是我在用的大概方案,不喜勿喷。
最佳答案
评论( 相关
后面还有条评论,点击查看>>