PHP生成token并自动更新。
在业务中,经常会遇到重复提交问题。token是一种解决表单重复提交的思路,token 原理大致为:
1:显示表单的那个 action 中使用 makeToken() 生成一个随机的 token值,称作 requestToken ,并存放在服务端(session或者cache中),并且传递一份到页面中
2:表单页面使用一个隐藏表单域获取后端传过来的 requestToken 值,该表单页面提交时会将此 requestToken 值一同提交到后端
3:在表单页面提交 actioin 后,服务端使用 checkToken(requestToken) 来比较服务端刚才下发的原 token 值,如果服务端存在 token 值并且与表单提交过来的值相等,证明是第一次提交。
4:每次校验过后服务端的 token 值会立即被清除,所以当用户重复提交时,后面的提交校验都再也无法通过。从而实现了防止重复提交的功能,checkToken 是在 synchronized 块中执行的保障了多线程下的安全性。
直接上代码:
WebToken.php:
/*
提供基础的token服务,保存在session,校验后自动更新。
使用场景:
提交表单前下发一个token,使用$this->makeToken();
提交表单的时候,带上这个token;提交后服务器校验此token,$this->checkToken($reqToken);并自动刷新不会重复。
来源:http://blog.csdn.net/xuduorui/article/details/59108024
*/
class WebToken {
const SIGN_KEY = '-O=M<.>
const SESSION_KEY = 'ATOKEN';
protected $token;
function __construct() {
session_start();
$this->init();
}
public function init() {
}
public function makeToken($expire = 300) {
$session_id = session_id();
$time = microtime(true);
$token = substr(md5($session_id.self::SIGN_KEY .$time), 3, 20);
$this->saveToSession($token, $expire);
return $token;
}
//验证token并自动刷新token
public function checkToken($token, $renew=1) {
// 取出token并作废session
$tokenInSession = $_SESSION[self::SESSION_KEY];
unset($_SESSION[self::SESSION_KEY]);
if ($renew) {
$this->token = null;//$this->makeToken();
}
// 空则返回检查失败
if (!$tokenInSession) {
return false;
}
// 检查session的token是否过期
if ($tokenInSession['e'] < time()) {
unset($_SESSION[self::SESSION_KEY]);
return false;
}
// 检查token值
if (!empty($token) && $tokenInSession['t']==$token) {
return true;
}
return false;
}
// 获取token并不刷新 public function getToken() { if (!$this->token) { $this->token = $this->makeToken(); } return $this->token; } protected function saveToSession($token, $expire=300) { $value = [ 't' => $token, //token //'c' => time()+$expire, //create_time 'e' => time()+(int)$expire, ]; $_SESSION[self::SESSION_KEY] = $value; //$ return $value; } }