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客戶端是否正常