防止表单重复提交,PHP生成token并自动更新

来源:互联网 发布:泰格软件安装 编辑:程序博客网 时间:2024/06/06 10:49

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:

<?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;
    }
}



0 0
原创粉丝点击