如何解决单击按钮X秒钟不活动后如何注销?
我正在一个简单的项目中,我有一个具有多个用户的登录系统,每个用户将登录并将表单条目保存在文件中。我正在尝试建立会话超时,以便在闲置2分钟后可以注销我。
- 我有
login.PHP
页,其中提供了用户名和密码。 - 如果登录成功,则将我重定向到
index.PHP
页,在该页上有两个文本框和一个按钮的表单。 - 在
index.PHP
页上,有一个Save Data
按钮,如果单击该按钮,它将调用save.PHP
,然后通过覆盖文件来保存表单项。 - 我的
logout
页面上也有index.PHP
链接,如果单击该链接,它将注销我并重定向到login.PHP
页面。
以上所有方法都可以正常工作。现在,我正在尝试建立此会话超时,以便它可以在闲置x分钟后将我注销,然后将我重定向到login.PHP
页。
<?PHP
declare(strict_types = 1);
// Start session.
session_start();
// Include helper functions.
require_once 'helpers.PHP';
// 2 mins in seconds
$inactive = 120;
if(isset($_SESSION['timeout']) ) {
$session_life = time() - $_SESSION['timeout'];
if($session_life > $inactive)
{
redirect('logout.PHP');
return;
}
}
$_SESSION['timeout'] = time();
// Redirect user to login page if not authenticated.
if (! check_auth()) {
redirect('login.PHP');
return;
}
?>
<!doctype html>
<html>
<head>
<title>Home</title>
</head>
<body>
<div>
<h1>Website Title</h1> <a href="logout.PHP">logout</a> </div>
<div>
<p>Welcome back,<?= $_SESSION['user_id'] ?>!</p>
</div>
<form method="post">
<input type="text" name="field1" />
<input type="text" name="field2" />
<input type="submit" name="submit" value="Save Data"> </form>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script>
$(function() {
$('form').submit(function(e) {
e.preventDefault();
$.post({
url: 'save.PHP',data: $(this).serialize(),}).done(response => {
response = JSON.parse(response);
if(response.message) {
alert(response.message);
}
});
});
});
</script>
</body>
</html>
<?PHP
declare(strict_types=1);
// Start session.
session_start();
// Include helper functions.
require_once 'helpers.PHP';
// 2 mins in seconds
$inactive = 120;
if(isset($_SESSION['timeout']) ) {
$session_life = time() - $_SESSION['timeout'];
if($session_life > $inactive)
{
redirect('logout.PHP');
return;
}
}
$_SESSION['timeout'] = time();
// Redirect user to login page if not authenticated.
if (! check_auth()) {
redirect('login.PHP');
return;
}
// save form entries in a file
<?PHP
declare(strict_types=1);
if (! function_exists('check_auth')) {
function check_auth(): bool
{
return isset($_SESSION['user_id']);
}
}
if (! function_exists('logout'))
{
function logout()
{
if (isset($_SESSION['user_id'])) {
$trace = json_decode(file_get_contents('current_user.txt'));
if ((int) $trace->user_id === $_SESSION['user_id']) {
$content = isset($trace->revoked_user_id)
? json_encode(['user_id' => $trace->revoked_user_id,'created_at' => (new DateTime('Now'))->format('Y-m-d H:i:s')])
: '';
file_put_contents('current_user.txt',$content);
}
unset($_SESSION['user_id']);
unset($_SESSION['timeout']);
}
}
}
if (! function_exists('redirect')) {
function redirect(string $url,int $status_code = 303): void
{
header('Location: ' . $url,true,$status_code);
die();
}
}
问题陈述
一旦在logout.PHP
和index.PHP
中空闲了2分钟的save.PHP
文件,我将重定向到该文件。这是我要注意的-
- 如果我在
index.PHP
页上,并且闲置了2分钟后,如果刷新浏览器,它将顺利退出我,没有任何问题,然后将我重定向到login.PHP
页。 - 现在让我们说,如果我再次进入
index.PHP
页面,并且在闲置2分钟后如果单击Save Data
按钮,则会在控制台上给我错误,但从技术上讲,它应该使我注销并将我重定向到login.PHP页面。
<script>
$(function() {
$('form').submit(function(e) {
e.preventDefault();
$.post({
url: 'save.PHP',}).done(response => {
response = JSON.parse(response);
if(response.message) {
alert(response.message);
}
});
});
});
</script>
在闲置2分钟后,只要单击Save Data
按钮,我的第2点就会收到json解析错误。并且response
变量的值在html中是完整的login.PHP
。我不确定为什么会这样。在它调用save.PHP
之前,我们需要在jquery本身中检查会话验证吗?
解决方法
总而言之,您的问题是由save.php
中的ajax请求重定向时引起的。
发生了什么事,redirect()
请求被透明处理并且结果由jQuery.ajax().done()
闭包处理,闭包试图为 JSON.parse(response);
的HTML调用login.php
。
单击按钮时,您应该能够通过在浏览器中查看开发人员工具(通常为F12)来验证这一点。
解决此问题的一般方法是确定请求是否为XMLHttpRequest
并发送不同的响应而不是重定向。
检测XMLHttpRequest
要确定请求是否来自jQuery.ajax()
,请检查X-Requested-With
请求标头。
isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest'
具有redirect
属性的JSON响应
此方法在响应中返回redirect
属性,并使用它从jQuery.ajax().done()
闭包中重定向。
helpers.php
if (! function_exists('redirect')) {
function redirect(string $url,int $status_code = 303): void
{
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') {
//do not redirect AJAX requests
echo json_encode(['redirect' => $url]);
} else {
header('Location: ' . $url,true,$status_code);
}
die();
}
}
index.php
$(function() {
"use strict";
$('form').submit(function(e) {
e.preventDefault();
$.post({
url: 'save.php',data: $(this).serialize(),}).done(response => {
response = JSON.parse(response);
if (response.redirect) {
//redirect user
window.location.href = response.redirect;
}
if (response.message) {
alert(response.message);
}
});
});
});
状态码响应
此方法返回200 Ok
以外的状态代码,而不是重定向,并在jQuery.ajax()
或statusCode:
方法中检查响应状态代码。
helpers.php
if (! function_exists('redirect')) {
function redirect(string $url,int $status_code = 303): void
{
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') {
//do not redirect AJAX requests
http_response_code(401); //Unauthorized - PHP 5.4+
echo $url; //optionally output the url
} else {
header('Location: ' . $url,$status_code);
}
die();
}
}
您可以在此处选择根据需要处理状态码。
对于最简单的方法,请检查fail()
jqXhr对象状态代码并改为执行JavaScript重定向。
index.php
$(function() {
"use strict";
$('form').submit(function(e) {
e.preventDefault();
$.post({
url: 'save.php',}).done(response => {
response = JSON.parse(response);
if (response.message) {
alert(response.message);
}
}).fail(jqXhr => {
if (jqXhr.status == 401) {
//redirect to specified url in the response text
window.location.href = jqXhr.responseText;
/* alternatively hard-code '/logout.php' */
}
});
});
});
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。