用户
 找回密码
 入住 CI 中国社区
搜索
查看: 5912|回复: 4
收起左侧

[讨论/交流] 发一个防止重复提交的 token验证

[复制链接]
发表于 2012-6-14 16:55:33 | 显示全部楼层 |阅读模式
本帖最后由 deader 于 2012-6-15 08:41 编辑

这个是大概一年前写的了,很久没再敲代码,自己都有些看不懂了。希望对大家有帮助。

MY_Controller.php

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
//基础控制器,用于被继承
class MY_Controller extends CI_Controller
{
        function __construct()
        {
                parent::__construct();
                $this->load->library('form_validation');
                $this->load->library('encrypt');
                .....
        }
        
        .........
        /**
         * 停止执行程序,给出错误信息,并写入错误日志。
         * 所有参数由helper提供
         *
         * @param $error_code 错误代码,用于区分错误类别
         * @param $error_level 错误级别
         * @param $error_message 错误提示信息
         */
        public function stop_doing($error_code='',$error_level='',$error_message='')
        {
                $this->load->library('slog');
                //写入日志
                $error_url = $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
                $this->slog->process_logs($error_url,$error_code,$error_level,$error_message);
                $rediret_url = 'http://'.$error_url;
                header("Content-type:text/html; charset=utf-8");         
                die("<script type=\"text/javascript\">alert(\"错误信息!\\n \\n错误代码:".$error_code."\\n错误级别:".$error_level."\\n错误信息:".$error_message."\"); window.navigate(\"$rediret_url\");</script>");               
        }


        /**
         * 获取表单的值
         * @param $name 表单元素名称
         * @param $type 提交方式,默认为post
         * @param $xxsf 让取得的数据经过跨站脚本过滤(XSS Filtering),默认为false,开启为true
         */
        public function obtain($name,$type='post',$xxsf=false)
        {
                if($type == 'post')
                {
                        return $this->input->post($name,$xxsf);
                }
                else if($type == 'get')
                {
                        return $this->input->get($name,$xxsf);
                }
                else
                {
                        return $this->input->get_post($name,$xxsf);
                }
        }
        
        ........
        
        /**
         * 令牌验证
         */
        const FORM_TOKEN_KEY = 'form_token_key';
        const INPUT_TOKEN_NAME = 'input_token_name';
        
        /**
         * 生成令牌
         *
         * @return string
         */
        public function gen_token()
        {               
                $hash = md5(uniqid(rand(), true));                                
                $token = sha1($hash);
                return $token;
        }
        
        /**
         * 生成session令牌
         *
         */
        public function gen_session_token()
        {
                //生成token
                $token = $this->gen_token();
                //删除session中原来的token
                $this->destroy_stoken();
                //将新的token注册到session
                $this->session->set_userdata(self::FORM_TOKEN_KEY,$token);
        }
        
        /**
         * 生成隐藏输入域表单
         *
         * @return 表单
         */
        public function gen_input()
        {
                $this->gen_session_token();
                $token_input =  "<input type=\"hidden\" name=\"".self::INPUT_TOKEN_NAME."\" value=\"".$this->session->userdata(self::FORM_TOKEN_KEY)."\" readonly=\"true\" /> ";
                return $token_input;
        }

        /**
         * 检测token是否合法,如果合法则继续执行,否则跳出
         *
         * @param string $token_input 页面提交的token
         */
        public function token_check($token_input)
        {
                // 检测session中是否已注册token
                if($this->is_stoken())
                {
                        if($token_input)
                        {
                                if($token_input == $this->session->userdata(self::FORM_TOKEN_KEY))
                                {
                                        $this->destroy_stoken();
                                }
                                else
                                {
                                        $this->destroy_stoken();                                       
                                        $this->stop_doing(error_code('d'),error_level('ce'),error_message('d_add'));
                                }
                        }
                        else
                        {
                                $this->destroy_stoken();
                                $this->stop_doing(error_code('v'),error_level('ce'),error_message('v_null'));        
                        }
                }
                else
                {
                        $this->destroy_stoken();
                        $this->stop_doing(error_code('s'),error_level('e'),error_message('s_check'));        
                }
        }

        /**
         * 销毁token
         *
         * @return bool
         */
        public function destroy_stoken()
        {
                $this->session->unset_userdata(self::FORM_TOKEN_KEY);
        return true;
        }
        
        /**
         * 检测token是否存在
         *
         * @return bool
         */
        public function is_stoken()
        {
                if($this->session->userdata(self::FORM_TOKEN_KEY))
                return true;
        else
                return false;
        }        
        
        /**
         * 合并二维数组的相同项
         */
        function array_multi_unique($ar)
        {
                 $ar = array_map('serialize', $ar);
                 $ar = array_unique($ar);
                 return array_map('unserialize', $ar);
        }

}




Controller 中使用如下:


<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Contents extends MY_Controller {

        function __construct()
        {
                parent::__construct();
                ......
        }
        
        public function index()
        {
                $this->users_list();
        }
               
        /*添加文章*/
        function content_add()
        {
                if($this->input->post('submit'))
                {                        
                        //令牌验证,是否非法提交表单
                        parent::token_check(parent:btain(parent::INPUT_TOKEN_NAME,'post',true));
               
                        if($this->form_validation->run() == true)
                        {               
                                $post_data = parent:btain('content');                        
                                $post_data['add_time'] = date('Y-m-d H:i:s');        
                                $post_data['add_person'] = $this->session->userdata('username');        
                                

                                if($this->m_contents->add_content($post_data))
                                {               
                                        session_start();
                                        $sessionid = $_SESSION['session_id'];
                                        $this->m_contents->del_tmp_img_upload($sessionid);                                
                                        redirect(s_url("/admin/contents/contents_list"));                                       
                                }
                                else
                                {
                                    parent::stop_doing(error_code('d'),error_level('ce'),error_message('d_add'));
                                }
                        }
                        else
                        {
                                parent::stop_doing(error_code('d'),error_level('e'),error_message('d_check'));        
                        }                                       
                }
                else
                {
                        $data['input_token'] = parent::gen_input();          
                        $data['editor'] = parent::editor("content[content]");
                        $data['allcates'] = $this->cates->fetch_view_data();        
                        $this->load->view('admin/contents/content_add',$data);
                }
        }

........
}



view中使用 如下:

<?php session_start();?>

<html xmlns="http://www.w3.org/1999/xhtml" class="off">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
<title></title>
<link href="<?php echo admin_path().'/'?>statics/css/base.css" rel="stylesheet" type="text/css" />
<script language="javascript" type="text/javascript" src="<?php echo admin_path().'/'?>statics/js/jquery.min.js"></script>
<script language="javascript" type="text/javascript" src="<?php echo admin_path().'/'?>statics/js/jquery.validate.js"></script>
</head>

<body leftmargin="8" topmargin="8" >
        <form action="/admin/contents/content_add" method="post" id="contentform" >
                ..............        
                <?php echo $input_token;?>
                  ...........                                
        </form>        
</body>
</html>


 楼主| 发表于 2012-6-14 17:11:05 | 显示全部楼层
怎么给代码字体变色呢,怎么变成“ [color=#ff0000]parent::token_check(parent:btain(parent::INPUT_TOKEN_NAME,'post',true));这种了
发表于 2012-6-14 18:11:31 | 显示全部楼层
围观下
发表于 2012-6-14 20:08:27 | 显示全部楼层
代码变色没有作用吧?为什么要变色,给自己看吗?
 楼主| 发表于 2012-6-15 08:37:17 | 显示全部楼层
变色的地方 当然是最需要注意的了

本版积分规则