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

[已解决] 一个困扰了很久的问题:防止表单重提交

[复制链接]
发表于 2012-6-4 15:27:00 | 显示全部楼层 |阅读模式
在CI中如何防止在刷新页面的时候表单重新提交呢?
据说是要跳转页面,但是始终搞不清怎么做
例如一个要把提交内容写入数据库 的表单,第一次已经成功并且转到成功页面去了,这个时候怎么做能不让刷新这个成功页面的时候重提交数据?
为这个问题已经困扰了N久了。。。。。。
求高人指条明路,跪谢~
发表于 2012-6-4 15:55:47 | 显示全部楼层
session 里面有个 last active,判断时间差。
发表于 2012-6-4 17:01:29 | 显示全部楼层
提交成功redirect走人
发表于 2012-6-4 17:30:01 | 显示全部楼层
PHP复制代码
 
if ($this->input->post('submit'))
{
......
 
redirect(...);
}
 
复制代码
发表于 2012-6-5 00:14:01 CI中国手机版 | 显示全部楼层
提交后重定向一次
来自: iPhone客户端
发表于 2012-6-14 16:06:43 | 显示全部楼层
嗯,重定向 我也是 这么干的
发表于 2012-6-14 16:18:29 | 显示全部楼层
很久没敲代码了,现在分享一个我以前写的 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');
  $this->load->model('admin/m_resources','m_resources');
  $this->load->model('admin/m_rights','m_rights');
  $this->load->model('admin/m_groups','m_groups');
 
  $this->_init(); //自动检查用户是否登录及权限判断
 }
 
 function _init()
 {
  //任何未登录的用户都初始化为guest组
  if( ! $this->session->userdata('groups'))
  {  
   $this->session->set_userdata(array('groups'=>'guest'));
  }
  $this->_check_url_permisson();
 }
 
 /**
  * 检查url权限,如果可以访问则正常进行,若无权限则提示并终止执行
  * 后续扩展字段权限
  * 注意:需要严格定义资源
  */

 function _check_url_permisson()
 {
  $current_url = $this->uri->uri_string() ? trim('/'.$this->uri->uri_string()) : '/welcome';
  @$resource_id = $this->m_resources->get_resources_by_url('id',$current_url)->result();
  $current_resource_id = $resource_id ? $resource_id[0]->id : 0;
 
  //如果当前角色为guest,则直接获取guest权限,不必登录
  if($this->session->userdata('groups') && $this->session->userdata('groups') == 'guest')
  {
   $res = $this->m_groups->get_group_by_name('guest')->result();
   $gid = $res[0]->id;
   @$guest_resource = $this->m_rights->get_resources_by_gid('resource_id',$gid)->result(); //guest组所拥有的权限  
   
   if($guest_resource && is_array($guest_resource))
   {
    foreach ($guest_resource as $grs)
    {
     $rest[] = $grs->resource_id;
    }
   }
   @$current_gp_res = @$rest; //guest组所拥有的权限
   $this->session->set_userdata('resources',$current_gp_res);
  }
 
  $my_resources = $this->session->userdata('resources');
 
  if($my_resources && is_array($my_resources) && @in_array($current_resource_id,$my_resources))
  {
   return ;  
  }
  else
  {    
   $this->_check_login();
  }  
 }
 
 
 /**
  * 检查是否登录
  *
  */

 function _check_login()
 {
  if($this->session->userdata('is_login') && $this->session->userdata('is_login') === true)
  {
   return ;
  }
  else
  {  
   redirect(s_url('/admin/auth/login'),'location');
  }
 }
 
 /**
  * 生成在线编辑器
  *
  * @param string $area 编辑器输入域名称
  * @param string $value 编辑器输入域值
  * @param number $width 宽度
  * @param unknown_type $height 高度
  * @param unknown_type $autoSave 是否自动保存
  * @return 编辑器域
  */

 public function editor($area,$value='',$width=630,$height=400,$autoSave=false)
 {
        //加载在线编缉器
      $this->load->library('seditor');
        $editor = $this->seditor->SunEditor($area);
        $editor->Value = $value;
        $editor->BasePath = 'editor';
        $editor->Height= $height;
        $editor->Width = $width;
        $editor->AutoSave = $autoSave;
        return $editor->Create();                
 }
 
 /**
  * 获取表单的值
  * @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);
  }
 }
 
 /*pagination 分页程序
 * $where: 需要分页的url地址,即完整的分页控制器/方法
 * $total_rows: 需要分页的数据总行数,通过查询数据库取得
 * $per_page: 每页中希望显示信息的数量
 * $uri_segment: URI的哪个部分包含页数
 * $num_links: 显示分页提示数量
 * $first_url: 分页链接首页链接
 */

 function _pagination($array)
 {
  $this->load->library('spagination');
  $config['pagination_fix'] = true; // 是否启用分页修正功能,如设置为 false 则和系统自带分页类无异
  $config['base_url'] = $array['where'];
  $config['total_rows'] = $array['total_rows'];
  $config['per_page'] = $array['per_page'];
  $config['uri_segment'] = $array['uri_segment'];  
  $config['num_links'] = $array['num_links'];
  //$config['first_url'] = $array['first_url']; // 分页链接首页链接
 
  //以下为默认设置,可以自行修改
  $config['full_tag_open'] = '<div class="pagination">'; //可根据需要改为<p>
  $config['full_tag_close'] = '</div>'; //可根据需要改为</p>
  $config['first_link'] = '首页';
  $config['last_link'] = '末页';
  $config['next_link'] = '下一页 >';
  $config['prev_link']= '< 上一页';
  $config['cur_tag_open'] = '<a class="current">';
  $config['cur_tag_close'] = '</a>';
 
  //修正样式开始
  $config['cur_rows_tag_open'] = '<a class="number">当前第 ';
  $config['cur_rows_tag_middle'] = ' ~ ';
  $config['cur_rows_tag_close'] = ' 条</a>';
  $config['total_rows_tag_open'] = ' <a class="number">共 ';
  $config['total_rows_tag_close'] = ' 条</a>';
  $config['total_pages_tag_open'] = ' <a class="number">计 ';
  $config['total_pages_tag_close'] = ' 页</a>';
  //修正样式结束
 
  /*以下配置默认关闭,可以通过css来美化分页效果,配置格式应为:
  * $config['first_tag_open'] = "<div class='someclass'>";
  * $config['first_tag_close'] = "</div>";
  */

  //$config['first_tag_open'] = '<div>';
  //$config['first_tag_close'] = '</div>';
  //$config['last_tag_open'] = '<div>';
  //$config['last_tag_close'] = '</div>';
  //$config['num_tag_open'] = '<div>';
  //$config['num_tag_close'] = '</div>';
  //$config['prev_tag_open'] = '<div>';
  //$config['prev_tag_close'] = '</div>';
  //$config['next_tag_open'] = '<div>';
  //$config['next_tag_close'] = '</div>';
   
  $this->spagination->initialize($config);  
 }
 
 /**
  * 停止执行程序,给出错误信息,并写入错误日志。
  * 所有参数由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>");  
 }
 
 /**
  * 令牌验证
  */

 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);
 }
 
}
复制代码

评分

参与人数 1威望 +5 收起 理由
Hex + 5 赞一个!

查看全部评分

发表于 2013-5-29 08:28:54 | 显示全部楼层
受教了

本版积分规则