deader 发表于 2012-6-14 16:55:33

发一个防止重复提交的 token验证

本帖最后由 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::obtain(parent::INPUT_TOKEN_NAME,'post',true));
               
                        if($this->form_validation->run() == true)
                        {               
                              $post_data = parent::obtain('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");
                        $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>


deader 发表于 2012-6-14 17:11:05

怎么给代码字体变色呢,怎么变成“ [color=#ff0000]parent::token_check(parent::obtain(parent::INPUT_TOKEN_NAME,'post',true));”这种了

s505208718 发表于 2012-6-14 18:11:31

围观下

布施 发表于 2012-6-14 20:08:27

代码变色没有作用吧?为什么要变色,给自己看吗?

deader 发表于 2012-6-15 08:37:17

变色的地方 当然是最需要注意的了 :lol
页: [1]
查看完整版本: 发一个防止重复提交的 token验证