基于token的數(shù)據(jù)通訊驗(yàn)證
當(dāng)用戶登錄成功后后端生成唯一token值 并緩存到redis中 以用戶id為鍵名token為值存儲
為了避免token泄露盡量不要直接傳輸token值給前端 而是通過token生成簽名 之后通過簽名做身份驗(yàn)證
登錄成功生成sign 并返回給前端
# 生成sign
// 你的密鑰
$key = 'Key_6@3.*78_xYQ98';
// 當(dāng)前用戶id
$userId = 100;
// 生成唯一 token
$token = sha1(microtime().uniqid(true).mt_rand(10000000,99999999));
// token存入redis ( 以userId為鍵名 以token為值 存一個鍵值對 )
$redis->set('token_'.$userId);
// 生成簽名
$sign = substr(sha1(sha1($key.$token.$userId)),6,30);
// 返回用戶id和簽名作為之后請求接口時的憑證
$info = array();
$info['userId'] = $userId;
$info['sign'] = $sign;
echo json_encode($info);
exit;
前端接收sign后 將sign和id以http請求頭方式發(fā)送給后端做身份驗(yàn)證
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script>
$(function(){
$.ajax({
url: '2.php',
type: 'POST',
dataType: 'JSON',
async: false,
data: {
uid: 100,
type: 1
},
// 設(shè)置http請求頭信息
beforeSend: function(request) {
// 將登錄時返回的用戶id和簽名以http形式傳給后端作為身份驗(yàn)證
request.setRequestHeader('userId',100);
request.setRequestHeader('sign',"skd5dkgk6j48fjdj");
// 時間戳為了防止數(shù)據(jù)被截獲修改
request.setRequestHeader('time',1501234567);
},
success: function(data){
},
error: function(){
}
});
})
</script>
后端驗(yàn)證sign信息
# 身份驗(yàn)證
// 如果是跨域請求加下面三句代碼
header('Access-Control-Allow-Origin:*');
header('Access-Control-Allow-Methods:POST,GET');
header('Access-Control-Allow-Headers:userId,sign,time');
// 獲取驗(yàn)證信息
$userId = (int)$_SERVER['HTTP_USERID'];
$sign = $_SERVER['HTTP_SIGN'];
$time = (int)$_SERVER['HTTP_TIME'];
// 驗(yàn)證請求是否超市 ( 如果請求時間和到達(dá)時間超過15秒則為超時 )
if($time + 15 < time()){
echo '請求超時';
exit;
}
// redis中通過userId查詢token信息
$token = $redis->get('token_'.$userId);
// 驗(yàn)證token
if($token){
// 你的密鑰
$key = 'Key_6@3.*78_xYQ98';
// 生成簽名
$serSign = substr(sha1(sha1($key.$token.$userId)),6,30);
// 簽名是否一致
if($serSign !== $sign){
echo '請重新登錄';
exit;
}
}else{
echo '請重新登錄';
exit;
}