“禁用 codeigniter 中的后退按钮?” - CodeIgniter 不可能
为什么不可能?
CodeIgniter 是一个Server Side Scripting Web Framework,它唯一的
对自己的环境负责,而不是对客户端负责,例如喜欢
JavaScript。因此,CI (CodeIgniter) does not affect Browser's Activity。
现在,我假设您想Prevent Views/Content being display for Un-Authorized User,当用户注销并尝试通过点击浏览器后退按钮查看仪表板或任何其他内容(仅供登录用户使用)时。
基本上,浏览器保持自我会话(活动)以更快地工作是非常直截了当的前言,我们可以在提交表单后通过返回按钮在表单中看到旧的输入数据。因此,一旦用户填写登录表单并提交表单,他们将被重定向到登录/仪表板页面,一旦他们单击注销按钮 CI 就会破坏用户的会话数据。但是在这个故事中 Browser Cache the Content and Form Data ,因此当用户点击历史返回按钮时,他们仍然能够看到来自数据或缓存内容。
那么,我们能做些什么呢?
好吧,我们可以在 Application Response 中使用 Cache Headers 来告诉浏览器,'嘿! Mozilla/Chrome/Browser Do Not Cache/Store 这个页面,它不可缓存并且总是敲门。但是..在这种情况下仍然存在一个小问题..
哦不!现在是什么:(?
好吧,缓存标头将通过从浏览器历史记录中删除内容来防止内容显示。但是,如果页面被任何类型的表单提交逗乐了,那么用户很可能会要求“Confirm Form Submission”。如果他们只是再次提交表单或按“F5”按钮表单将通过相同的先前数据或表单输入再次提交。
好的,那么我们如何在 CodeIgniter.. 中处理这个 Confirm Form Submission 呢?
我们可以使用OTT (One Time Token), CSRF (Cross-Site Request Forgery) Protection or Any Other Method which is Intend to Made only for One Time。就像 CI 有 CSRF Regenerate 选项,每次都创建一个新的 CSRF Toke。您可以在 CSRF 部分 $config['csrf_regenerate'] 的 application/config.php 中找到该选项,只需将其设为 $config['csrf_regenerate'] = TRUE。
仍然可以提交表单..?
哦,是的!为什么.. 因为你设置了 $config['csrf_regenerate'] = TRUE; 但是 $config['csrf_expire'] 仍然有很长的时间来过期旧 CSRF 令牌。因此,如果您设置了$config['csrf_expire'] = 60;,那么您将无法通过浏览器后退按钮重新提交缓存表单。因为旧的 CSRF 令牌已过期且 CI 在 2 分钟后无法识别相同的旧表单,所以我们在这里将 Expire CSRF 令牌搁置了 2 分钟......Yuhooo !!
嘿嘿!!好像解决了:)是的!
这是全新的 Controller Logins.php 代码:
<?php
// security first always....
(defined('BASEPATH') or exit('No direct script access allowed'));
/**
* Class Controller
*
* Class Logins Controller to handle login & logout
*/
class Logins extends CI_controller
{
/**
* Class Constructor
*/
public function __construct()
{
// execute parent class constructor
parent::__construct();
// load helpers
$this->load->helper(array('form', 'url', 'security'));
// load lib
$this->load->library('form_validation');
// prevent from Browser Cache
$this->output->set_header('Last-Modified: ' . gmdate("D, d M Y H:i:s") . ' GMT');
$this->output->set_header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
$this->output->set_header('Pragma: no-cache');
$this->output->set_header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
}
/**
* Default method to execute if method name missing
* @return [type] [description]
*/
public function index()
{
// check if user login or not
if (!$this->session->userdata('name')) {
// show login view
$this->load->view('match');
}
// if already logged in, show other view
else {
// get name from session login flag
$name = $this->session->userdata('name');
// load view
$this->load->view('match', $name);
}
}
/**
* login Form POST Method to verify Users identity
* @return [type] [description]
*/
public function getdata()
{
// if POST made then only
if ($this->input->post()) {
$rules = array(
array(
'field' => 'name',
'label' => 'Name',
'rules' => 'trim|required|xss_cleaned|min_length[3]|max_length[25]',
),
array(
'field' => 'pass',
'label' => 'Secret Password',
'rules' => 'required',
),
);
// form validation
$this->form_validation->set_rules($rules);
// check validation
if ($this->form_validation->run() === false) {
$this->load->view('match');
} else {
// safe from CSRF, use 2nd param as TRUE in POST
$name = $this->input->post('name', true);
$pass = $this->input->post('pass', true);
// Query Where Conditioning
$array = array('name' => $name, 'pass' => $pass, 'status' => 'registered');
// produces: WHERE name = 'user-name' AND pass = '***' AND status = 'registered'
$this->db->where($array);
// get from MySQL Table
$query = $this->db->get('form');
// if result
if ($query->num_rows() > 0) {
$sess_login = array(
'name' => $name,
);
// set session login flag
$this->session->set_userdata($sess_login);
// load view
$this->load->view('match', $name);
} else {
redirect('logins');
}
}
} else {
redirect('logins');
}
}
/**
* Log Out Method
* @return [type] [description]
*/
public function userlogout()
{
$this->session->unset_userdata('name');
redirect('logins');
}
}
这是全新的 Views match.php 代码:
<?php
$name = $this->session->userdata('name');
?>
<!DOCTYPE html>
<html>
<head>
<title>CodeIgniter First Login</title>
<link rel="stylesheet" type="text/css" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script type="text/javascript" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<div class="jumbotron vertical-center">
<?php if ($name !== false): ?>
<div class="container">
<div class="alert alert-success">Wohoo!! You made it.. <?php echo $name ?> <a href="<?php echo base_url()?>logins/userlogout" class="btn btn-danger">Log Out</a></div>
</div>
<?php else: ?>
<div class="container">
<?php echo (validation_errors()) ? '<div class="alert alert-danger">'.validation_errors().'</div>' : ''; ?>
<?=form_open('logins/getdata', 'class="form-controller"'); ?>
<fieldset>
<legend>Login Information</legend>
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" name="name" id="name" placeholder="Please enter your user name here" value="<?php echo set_value('name'); ?>">
</div>
<div class="form-group">
<label for="password">Secret Password</label>
<input type="password" class="form-control" id="password" name="pass" placeholder="Please enter your password here" value="<?php echo set_value('pass'); ?>">
</div>
</fieldset>
<div class="form-group row">
<div class="offset-sm-2 col-sm-10">
<button type="submit" class="btn btn-primary">Sign in</button>
</div>
</div>
<?=form_close();?>
</form>
</div>
<?php endif ?>
</div>
</body>
</html>
config.php
$config['csrf_protection'] = TRUE;
$config['csrf_token_name'] = 'csrf_test_name';
$config['csrf_cookie_name'] = 'csrf_cookie_name';
$config['csrf_expire'] = 120; // 2 minutes
$config['csrf_regenerate'] = TRUE;