使用websocket防止app登錄接口的token劫持

token的作用:和PC登陸的session一樣,作爲用戶進入的唯一票據

例如:app與服務器端的接口、java與php之間不同程序的接口,這些接口一般通過json格式傳輸數據

所以爲了保證移動端和服務端數據傳輸相對安全,需要對接口進行加密傳輸

1、token的設計目的: 
因爲APP端沒有和PC端一樣的session機制,所以無法判斷用戶是否登陸,以及無法保持用戶狀態,所以就需要一種機制來實現session,這就是token的作用,token是用戶登陸的唯一票據,只要APP傳來的token和服務器端一致,就能證明你已經登陸,有權限(就和你去看電影一樣,需要買票,拿着票就能進了)

 

第一種方式,  使用普通ajax方式

1、用戶用密碼登錄成功後,服務器返回token給客戶端;

2、客戶端將token保存在本地,發起後續的相關請求時,將token發回給服務器;

3、服務器檢查token的有效性,有效則返回數據,若無效,分兩種情況:

token錯誤,這時需要用戶重新登錄,獲取正確的token

然而,此種驗證方式存在一個安全性問題:

當登錄接口被劫持時,黑客就獲取到了用戶token,後續則可以對該用戶做任何事情了

當然 你可以使用 HTTPS或者限制token的有限時間 來降低這種 被劫持的機會, 但是還是會被劫持利用

 

第二種方式,  使用websocket方式來進行api接口

原理:

一般websocket服務器 都會保存, 客戶端的id序號(唯一的)

我們只要唯一id 把這個也作爲判斷的條件,  這樣即使客戶端token被劫持了也沒有關係

工具:  workerman(websocket) + php 爲例子 主要代碼爲下____workerman庫可以去 官網下載

<?php   
use Workerman\Worker;  
//引入socket庫
include __DIR__ . '/vendor/autoload.php';
$ws_worker = new Worker("websocket://0.0.0.0:8000");
// 只啓動1個進程,這樣方便測試客戶端之間傳輸數據
$ws_worker->count = 1;
$ws_worker->connection_uids = array();
 
$ws_worker->onWorkerStart=function($worker){
	echo '開啓worket start';
};

//websocket開始連接
$ws_worker->onWebSocketConnect = function($connection , $http_header)
{
	echo 'open connect';
};

//客戶端發送過來的消息
$ws_worker->onMessage = function($connection, $data){
    global $ws_worker;
	$jsonData = array();
	$jsonData['status'] = 0;
	$jsonData['msg'] = '未知錯誤';
	//獲取前端發來的數據並解析
    $clientJson = json_decode($data);
	if(!isset($clientJson->type)){ //錯誤的提交
		$jsonData['msg'] = 'error submit data';
		$result = json_encode($jsonData);
		$connection->send($result); 
		return;	
	}
	$askType = $clientJson->type; //客戶端請求類型
	$jsonData['type'] = $askType; //保存客戶端請求類型
	$clientId = $connection->id; //當前客戶端唯一的id號(這是重點)
	//判斷請求類型
    switch($askType){
        case 'login': //登錄
			//進行登錄操作
			$username = $clientJson->username; //用戶名
			$pwd = $clientJson->pwd;  //密碼
			$loginArr = qlogin($username, $pwd, $clientId); //登錄驗證生成客戶端token和websocket token
			$loginStatus = $loginArr['status'];
            if($loginStatus){
				$jsonData['status'] = 1;
				$jsonData['token'] = $loginArr['token'];
				$jsonData['wstoken'] = $loginArr['wstoken'];
				$jsonData['msg'] = $loginArr['msg'];				
			}else{
				$jsonData['status'] = 0;
				$jsonData['msg'] = $loginArr['msg'];				
			}
            break;
		case 'getuserinfo': //獲取用戶信息
			$bwsAuth = wsAuthVerify($clientId); //驗證當前的websocket id是否和數據庫一樣
			if(!$bwsAuth){ //非法提交
				$jsonData['msg'] = 'Illegal Sources';
				$result = json_encode($jsonData);
				$connection->send($result); 
				return;
			}
			$token = $clientJson->token;
			//判斷token是否正確
			$userInfo = getMemberInfo($token);
			$userStatus = $userInfo['status'];
			if($userStatus){
				$jsonData['status'] = 1;
				$jsonData['token'] = $token;
				$jsonData['type'] = $askType;
				$userid = $userInfo['userid'];
				$jsonData['msg'] = 'userinfo success';						
			}else{
				$jsonData['msg'] = $userInfo['msg'];	
			}
			break;
        default:
            break;
    }
	$result = json_encode($jsonData);
	$connection->send($result);
	return;	
};
//websocket關閉
$ws_worker->onClose = function($connection){
    global $ws_worker;
	echo 'close';
};

登錄判斷函數

判斷websocket客戶端是否正常

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章