单击按钮 X 分钟不活动后如何注销?
How to logout after X minutes of inactivity on button click?
我正在做一个简单的项目,我有一个包含多个用户的登录系统,每个用户都将登录并将表单条目保存在一个文件中。我正在尝试建立会话超时,以便在 2 分钟不活动后它可以将我注销。
- 我在
login.php
页面上提供了我的用户名和密码。
- 如果登录成功,它会将我重定向到
index.php
页面,我在该页面上有两个文本框和一个按钮。
- 在
index.php
页面上我有 Save Data
按钮,如果我点击它调用 save.php
然后它通过覆盖文件保存表单条目。
- 我的
index.php
页面上也有 logout
link,如果我单击它,它将注销我并重定向到 login.php
页面。
以上一切正常。现在我正在尝试构建此会话超时,以便它可以在 x 分钟不活动后将我注销并将我重定向到 login.php
页面。
这是我的 index.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>
这是我的 save.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;
}
// save form entries in a file
这是我的 helpers.php
文件:
<?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();
}
}
问题陈述
一旦 index.php
和 save.php
空闲 2 分钟,我将重定向到 logout.php
文件。这是我注意到的 -
- 如果我在
index.php
页面上并且在 2 分钟不活动后,如果我刷新我的浏览器然后它会正常注销我并且没有任何问题并将我重定向到 login.php
页面。
- 现在假设如果我再次进入
index.php
页面并在 2 分钟不活动后单击 Save Data
按钮然后它会在我的控制台上给我错误,但从技术上讲它应该记录我out 并将我重定向到 login.php 页面。
下面是我在 index.php
页面中的 ajax 调用 -
<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>
当我在 2 分钟不活动后单击 Save Data
按钮时,我的第 2 点会出现 json 解析错误。 response
变量的值在 html 中已满 login.php
。我不确定为什么会这样。我们是否需要在 jquery 调用 save.php
之前检查会话验证?
总之,您的问题是由 ajax 请求时 save.php
中发生的重定向引起的。
发生的事情是 redirect()
请求被透明处理,结果由 jQuery.ajax().done()
闭包处理,它试图为 HTML 调用 JSON.parse(response);
login.php
。
单击按钮时,您应该能够通过在浏览器中查看开发人员工具(通常是 F12)来验证这一点。
解决此问题的一般方法是确定请求是否为 XMLHttpRequest
并发送不同的响应而不是重定向。
检测 XMLHttpRequest
要确定请求是否来自 jQuery.ajax()
,您可以检查 X-Requested-With
请求 header。
isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest'
JSON 响应 redirect
属性
这种方法 returns 在响应中使用 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);
}
});
});
});
状态代码响应
此方法 returns 一个不同于 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, true, $status_code);
}
die();
}
}
在这里您可以根据需要选择对状态码进行处理。
对于最简单的方法,检查 fail()
jqXhr object 状态代码并改为执行 javascript 重定向。
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.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' */
}
});
});
});
我正在做一个简单的项目,我有一个包含多个用户的登录系统,每个用户都将登录并将表单条目保存在一个文件中。我正在尝试建立会话超时,以便在 2 分钟不活动后它可以将我注销。
- 我在
login.php
页面上提供了我的用户名和密码。 - 如果登录成功,它会将我重定向到
index.php
页面,我在该页面上有两个文本框和一个按钮。 - 在
index.php
页面上我有Save Data
按钮,如果我点击它调用save.php
然后它通过覆盖文件保存表单条目。 - 我的
index.php
页面上也有logout
link,如果我单击它,它将注销我并重定向到login.php
页面。
以上一切正常。现在我正在尝试构建此会话超时,以便它可以在 x 分钟不活动后将我注销并将我重定向到 login.php
页面。
这是我的 index.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>
这是我的 save.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;
}
// save form entries in a file
这是我的 helpers.php
文件:
<?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();
}
}
问题陈述
一旦 index.php
和 save.php
空闲 2 分钟,我将重定向到 logout.php
文件。这是我注意到的 -
- 如果我在
index.php
页面上并且在 2 分钟不活动后,如果我刷新我的浏览器然后它会正常注销我并且没有任何问题并将我重定向到login.php
页面。 - 现在假设如果我再次进入
index.php
页面并在 2 分钟不活动后单击Save Data
按钮然后它会在我的控制台上给我错误,但从技术上讲它应该记录我out 并将我重定向到 login.php 页面。
下面是我在 index.php
页面中的 ajax 调用 -
<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>
当我在 2 分钟不活动后单击 Save Data
按钮时,我的第 2 点会出现 json 解析错误。 response
变量的值在 html 中已满 login.php
。我不确定为什么会这样。我们是否需要在 jquery 调用 save.php
之前检查会话验证?
总之,您的问题是由 ajax 请求时 save.php
中发生的重定向引起的。
发生的事情是 redirect()
请求被透明处理,结果由 jQuery.ajax().done()
闭包处理,它试图为 HTML 调用 JSON.parse(response);
login.php
。
单击按钮时,您应该能够通过在浏览器中查看开发人员工具(通常是 F12)来验证这一点。
解决此问题的一般方法是确定请求是否为 XMLHttpRequest
并发送不同的响应而不是重定向。
检测 XMLHttpRequest
要确定请求是否来自 jQuery.ajax()
,您可以检查 X-Requested-With
请求 header。
isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest'
JSON 响应 redirect
属性
这种方法 returns 在响应中使用 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);
}
});
});
});
状态代码响应
此方法 returns 一个不同于 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, true, $status_code);
}
die();
}
}
在这里您可以根据需要选择对状态码进行处理。
对于最简单的方法,检查 fail()
jqXhr object 状态代码并改为执行 javascript 重定向。
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.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' */
}
});
});
});