php - 为什么要创建多个 PHP 会话?
问题描述
Reeeallly希望有人可以在这里帮助我,因为这已经困扰了我一段时间,并且没有多少谷歌搜索有帮助。我是一名网站开发者,他正在尝试为非营利组织创建参赛应用程序。
当我在我的 Web 应用程序中加载一个页面时,我看到在我的自定义 Web 应用程序文件夹中创建了 2 个会话(我只期待一个):
当然,这是有问题的,因为我正在设置会话值以供下游 PHP 代码使用,并且根据抓取的内容,我的代码在检查我的 CSRF 令牌时失败。
以下是正在发生的事情(Chrome 浏览器):
- 强制重新加载页面以更新缓存,因为我正在处理 JS/CSS 更改;我不提交表格或在任何地方导航。
- 我的日志文件显示了两个不同的 session_id: session_id:ccbbhescjqevk02id43nf6tmgc 和 session_id:vf7fgnu92up1uim9nlup1h8nlu(后者仅在页面加载的最后创建)
- 我正在向我的表单添加一个 CSRF 令牌,该令牌通过 POST 提交,并在我的下游 PHP 文件中检查它,但有时这会失败,因为它不在它正在使用的会话中。
这是我的页面:
<?php
// include setConfig
require_once '../../../private/contest/include/setConfig.php';
// include startSession
require_once '../../../private/contest/include/startSession.php';
if (session_status() == PHP_SESSION_NONE) {
startWFsession('entry_form');
}
$_SESSION['current_time'] = time();
// Blank out assoc array of new entry details that are used by printout.php
unset($_SESSION['newEntryRec']);
$pageName = 'entryForm';
$pageVer = '1.0.0';
$ip = getUserIP();
$sessionID = session_id();
// Generate form token for CSRF protection
if (!isset($_SESSION['token'])) {
$_SESSION['token'] = generateCSRFtoken($sessionID, $ip);
}
$token = $_SESSION['token'];
if (DEV_MODE) {
$log->debug('CSRF token for this session:',
array('file:' => basename(__FILE__),
'line#:' => __LINE__,
'session_id' => $sessionID,
'IP' => $ip,
'$_SESSION["token"]' => bin2hex($_SESSION['token'])));
}
?>
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta name="robots" content="noindex,nofollow" />
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
.
.
.
<title>Testing 123</title>
<noscript>
<!-- Hide page contents if JS is disabled -->
<style>
.pagecontainer {display:none;}
</style>
</noscript>
<script src="js/entrylogic_v1.0.0.js"></script>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
</head>
<body>
<div>
<?php include('../common/html/navbar.htm');?>
</div>
<noscript>
<div class="noscriptmsg">
<h4><span class="red">JavaScript</span> is disabled on your browser. You will not be able to use this application until it is enabled.</h4>
<h5>Please refer to your browser's specific configuration details to change this setting.</h5>
</div>
</noscript>
<div class="pagecontainer">
<div id="outline">
<div class="container">
<?php
// Determine if this year's contest is open
// ========================================
$current_time = new DateTime('now');
$chkContest = isContestOpen($current_time, $sessionID, $ip);
$log->debug('Function isContestOpen check ',
array('file:' => basename(__FILE__),
'line#:' => __LINE__,
'session_id' => $sessionID,
'IP' => $ip,
'chkContest' => $chkContest));
if ($chkContest != 'open' || is_null($chkContest)) {
exit($chkContest);
}
// Got this far, so contest is open
?>
<div class="form-row">
<!--<div class="center">-->
<form id="entryForm" name="entryForm" class="form-horizontal" enctype="multipart/form-data">
<!-- CSRF protection -->
<input type="hidden" name="token" value="<?php echo $token; ?>" />
<div class="entryFields">
<div>
<fieldset class="scheduler-border">
<legend class="scheduler-border">Entrant Info</legend>
<div class="form-group">
<div class="col-sm-4">
<label for="first-name" class="sr-only">First name</label>
<input id="first-name" name="fName" class="form-control" type="text" placeholder="First name [required]" title="Requried. Max <?php echo FORM_NAME_FLD_LENGTH; ?> characters"
maxlength="<?php echo FORM_NAME_FLD_LENGTH; ?>" data-wf-fld-len="<?php echo FORM_NAME_FLD_LENGTH; ?>" required autofocus autocomplete="given-name">
</div>
<div class="col-sm-8">
<label for="last-name" class="sr-only">Last name</label>
<input id="last-name" name="lName" class="form-control" type="text" placeholder="Last name [required]" title="Requried. Max <?php echo FORM_NAME_FLD_LENGTH; ?> characters"
maxlength="<?php echo FORM_NAME_FLD_LENGTH; ?>" data-wf-fld-len="<?php echo FORM_NAME_FLD_LENGTH; ?>" required autocomplete="family-name">
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<label for="email" class="sr-only">Email</label>
<input id="email" name="email" class="form-control" type="email" placeholder="Email [required]"
title="Required. Max <?php echo FORM_EMAIL_FLD_LENGTH; ?> characters (e.g. bela@transylvania.com)" maxlength="<?php echo FORM_EMAIL_FLD_LENGTH; ?>"
data-wf-fld-len="<?php echo FORM_EMAIL_FLD_LENGTH; ?>" required autocomplete="home email">
</div>
</div>
</fieldset>
</div>
<div>
<fieldset class="scheduler-border">
<legend class="scheduler-border">Model Info</legend>
<div class="form-group">
<div class="col-sm-12">
<label for="model_name" class="sr-only">Model name</label>
<textarea rows="2" id="model_name" name="modelName" class="form-control textarea-group-lg" placeholder="Title or name of entry [required]"
title="Required. Max <?php echo FORM_MODELNAME_FLD_LENGTH; ?> characters" maxlength="<?php echo FORM_MODELNAME_FLD_LENGTH; ?>"
data-wf-fld-len="<?php echo FORM_MODELNAME_FLD_LENGTH; ?>" required></textarea>
</div>
</div>
<div class="center">
<div class="form-group"><!--category -->
<div class="col-sm-12">
<label for="category" class="sr-only">Category</label>
<!-- https://developer.snapappointments.com/bootstrap-select/options/#default-settings -->
<select id="category" name="category" class="selectpicker show-tick" data-show-subtext="true" data-size="10" data-live-search="true" data-width="auto"
title="Category [required]" data-header="Select the most appropriate category:" size="1" required>
<?php
$log->debug('About to call getCategories() ...',
array('file:' => basename(__FILE__),
'line#:' => __LINE__,
'session_id' => $sessionID,
'IP' => $ip));
// Call function to get categories for current year
$result = getCategories(date('Y'), $sessionID, $ip);
if (!empty($result)){?>
<option disabled selected value>Category [required]</option>
<?php
for ($i = 0; $i < count($result); $i++){
//echo nl2br ($result[$i]["Category"] . "\n");?>
<option value="<?php echo $result[$i]['ID']; ?>" data-subtext="<?php echo htmlspecialchars($result[$i]['Description']); ?>"><?php echo htmlspecialchars($result[$i]['Category']); ?></option><?php
}
} else {?>
<option disabled selected value>No categories exist for current year</option><?php
}
?>
</select>
</div>
</div><!--end of category -->
<?php
$log->debug('After call getCategories() ...',
array('file:' => basename(__FILE__),
'line#:' => __LINE__,
'session_id' => $sessionID,
'IP' => $ip));
?>
</div>
<div class="form-group">
<div class="col-sm-12">
<label for="exampleFormControlFile1">Select up to four (4) model photos (PNG or JPG only):</label>
<input type="file" class="form-control-file" id="modelPhoto1" name="modelPhoto1" accept=".jpg, .png, .jpeg|image/*" required>
<input type="file" class="form-control-file" id="modelPhoto2" name="modelPhoto2" accept=".jpg, .png, .jpeg|image/*">
<input type="file" class="form-control-file" id="modelPhoto3" name="modelPhoto3" accept=".jpg, .png, .jpeg|image/*">
<input type="file" class="form-control-file" id="modelPhoto4" name="modelPhoto4" accept=".jpg, .png, .jpeg|image/*">
</div>
</div>
</fieldset>
</div>
<div>
<fieldset class="scheduler-border">
<legend class="scheduler-border">Terms and Conditions</legend>
<p style="text-align:left;font-size:x-small;margin:0px 0px 0px 0px">I grant WANT-A-FEST permission to use my model photos in their marketing materials without limitation or restriction.</p>
<p style="margin-top:4px;margin-bottom:4px;font-size:small"><input id="acceptAgrmt" type="checkbox" name="acceptAgrmt" value="" required> I accept the Terms and Conditions</p>
</fieldset>
</div>
<div id='recaptcha' class="g-recaptcha" data-sitekey="<?php echo RECAPTCHA_SITE_KEY; ?>" data-callback="onSubmit" data-size="invisible"></div>
<div class="center">
<div><!--form buttons-->
<input type="submit" id="formsubmit" name="mysubmit" class="btn btn-danger" value="Submit">
<input type="reset" id="formreset" class="btn btn-warning" value="Clear Form">
</div><!--end of form buttons-->
<div class="center" style="margin-top: 10px;font-size: x-small">
This site is protected by reCAPTCHA and the Google
<a href="https://policies.google.com/privacy">Privacy Policy</a> and
<a href="https://policies.google.com/terms">Terms of Service</a> apply.
</div>
</div>
</div>
</form>
<!--</div>-->
</div>
</div><!--container-->
</div><!--outline-->
</div><!--pagecontainer-->
<div class="modalLoading">
<?php
$log->debug('Before loading modalLoading.htm ...',
array('file:' => basename(__FILE__),
'line#:' => __LINE__,
'session_id' => $sessionID,
'IP' => $ip));
?>
<?php include('../common/html/modalLoading.htm');?>
<?php
$log->debug('After loading modalLoading.htm ...',
array('file:' => basename(__FILE__),
'line#:' => __LINE__,
'session_id' => $sessionID,
'IP' => $ip));
?>
</div>
<!-- SHOPPING CART START -->
<?php
$log->debug('Before loading shopping cart stuff ...',
array('file:' => basename(__FILE__),
'line#:' => __LINE__,
'session_id' => $sessionID,
'IP' => $ip));
?>
<?php include('../common/html/jquery_dlg_clear_cart.htm');?>
<?php include('../common/html/jquery_dlg_delete_entry.htm');?>
<?php
$log->debug('After loading shopping cart stuff ...',
array('file:' => basename(__FILE__),
'line#:' => __LINE__,
'session_id' => $sessionID,
'IP' => $ip));
?>
<!-- SHOPPING CART END -->
<div class="footer">
<?php
$log->debug('Before loading footer.htm ...',
array('file:' => basename(__FILE__),
'line#:' => __LINE__,
'session_id' => $sessionID,
'IP' => $ip));
?>
<?php include('../common/html/footer.htm');?>
<?php
$log->debug('After loading footer.htm ...',
array('file:' => basename(__FILE__),
'line#:' => __LINE__,
'session_id' => $sessionID,
'IP' => $ip));
?>
</div>
</body>
</html>
我的自定义会话开始功能:
function startWFsession($sessionName) {
global $log, $entryFormCookieParams;
// From http://php.net/manual/en/function.session-set-cookie-params.php :
session_set_cookie_params(
$entryFormCookieParams["lifetime"],
$entryFormCookieParams["path"],
$entryFormCookieParams["domain"],
$entryFormCookieParams["secure"],
$entryFormCookieParams["httponly"]
);
// Set custom PHP session save path before every call to session_start() as per Dean Brook's (Iglou) suggestion
ini_set('session.save_path', PHP_SESSION_FLDR);
// Set session timeout to be the same as the cookie
ini_set('session.gc-maxlifetime', $entryFormCookieParams["lifetime"]);
// Set session srict mode on (rejects session IDs not initialized by the server)
ini_set('session.use_strict_mode', true);
if (!empty($sessionName)) {
session_name($sessionName);
}
session_start();
setcookie(session_name(),session_id(),time()+$entryFormCookieParams["lifetime"]);
$log->debug('Session started or resumed - check session_id',
array('file:' => basename(__FILE__),
'line#:' => __LINE__,
'session_id' => session_id(),
'session_name' => session_name(),
'Cookie lifetime' => $entryFormCookieParams["lifetime"],
'Cookie path' => $entryFormCookieParams["path"],
'Cookie domain' => $entryFormCookieParams["domain"],
'Cookie secure' => $entryFormCookieParams["secure"],
'Cookie httponly' => $entryFormCookieParams["httponly"],
'IP' => getUserIP()
));
return is_session_started() ? TRUE : FALSE;
}
我的日志文件输出:
[2020-06-09 19:13:12] WF.DEBUG: Reading config settings and setting file includes {"file:":"setConfig.php","line#:":48,"$_SERVER[\"DOCUMENT_ROOT\"]":"/Users/Ross/Dropbox/htdocs/wantafest_mamp_pro/public_html","DB_SERVERNAME":"localhost","DB_NAME":"wantafest_contest_online","DB_SERVER_PORT":3311,"DB_USERNAME":"root","EMAIL_HOST":"mail.wonderfest.com","EMAIL_SMTP_AUTH":true,"EMAIL_USERNAME":"x.com","EMAIL_SMTP_SECURE":"tls","EMAIL_SERVER_PORT":587,"EMAIL_SEND_LOGS_TO":"y.com","EMAIL_SEND":false,"LOG_FLDR":"/Users/Ross/Dropbox/htdocs/wantafest_mamp_pro/private/contest/logs/","CACHE_FLDR":"/Users/Ross/Dropbox/htdocs/wantafest_mamp_pro/private/contest/cached-files","CACHE_EXPIRE_SQL_SEC":59,"CACHE_EXPIRE_PRINTOUT_SEC":360,"PHOTOS_FLDR":"/Users/Ross/Dropbox/htdocs/wantafest_mamp_pro/private/contest/photos/","BO_EXPIRE_SESSION_AFTER_SEC":900,"$entryFormCookieParams[\"lifetime\"]":1800,"$entryFormCookieParams[\"path\"]":"/","$entryFormCookieParams[\"domain\"]":".localhost","$entryFormCookieParams[\"secure\"]":false,"$entryFormCookieParams[\"httponly\"]":true,"PHP_SESSION_FLDR":"/Users/Ross/Dropbox/htdocs/wantafest_mamp_pro/sessions"}
[2020-06-09 19:13:12] WF.DEBUG: Session started or resumed - check session_id {"file:":"startSession.php","line#:":41,"session_id":"**ccbbhescjqevk02id43nf6tmgc**","session_name":"entry_form","Cookie lifetime":1800,"Cookie path":"/","Cookie domain":".localhost","Cookie secure":false,"Cookie httponly":true,"IP":"::1"}
[2020-06-09 19:13:12] WF.DEBUG: PHP version is 5.4.0 or greater {"file:":"startSession.php","line#:":65,"IP":"::1","phpversion()":"7.4.2","session_status()":2}
[2020-06-09 19:13:12] WF.DEBUG: generateCSRFtoken {"file:":"commonfunctions.php","line#:":910,"session_id":"**ccbbhescjqevk02id43nf6tmgc**","IP":"::1","token":"64373566386535363733353835303938623364643931333838643636643030373736346332396136303432626634306266303366383433386361633530376465"}
[2020-06-09 19:13:12] WF.DEBUG: CSRF token for this session: {"file:":"entryForm_v1.0.0.php","line#:":36,"session_id":"**ccbbhescjqevk02id43nf6tmgc**","IP":"::1","$_SESSION[\"token\"]":"64373566386535363733353835303938623364643931333838643636643030373736346332396136303432626634306266303366383433386361633530376465"}
[2020-06-09 19:13:12] WF.DEBUG: Bypassing date check - DEV MODE {"file:":"commonfunctions.php","line#:":176,"session_id":"**ccbbhescjqevk02id43nf6tmgc**","IP":"::1"}
[2020-06-09 19:13:12] WF.DEBUG: Function isContestOpen check {"file:":"entryForm_v1.0.0.php","line#:":253,"session_id":"**ccbbhescjqevk02id43nf6tmgc**","IP":"::1","chkContest":"open"}
[2020-06-09 19:13:12] WF.DEBUG: About to call getCategories() ... {"file:":"entryForm_v1.0.0.php","line#:":331,"session_id":"**ccbbhescjqevk02id43nf6tmgc**","IP":"::1"}
[2020-06-09 19:13:12] WF.DEBUG: Cache key "categories" found. {"file:":"commonfunctions.php","line#:":393,"session_id":"**ccbbhescjqevk02id43nf6tmgc**","IP":"::1","Year":"2020"}
[2020-06-09 19:13:12] WF.DEBUG: After call getCategories() ... {"file:":"entryForm_v1.0.0.php","line#:":359,"session_id":"**ccbbhescjqevk02id43nf6tmgc**","IP":"::1"}
[2020-06-09 19:13:12] WF.DEBUG: Before loading modalLoading.htm ... {"file:":"entryForm_v1.0.0.php","line#:":418,"session_id":"**ccbbhescjqevk02id43nf6tmgc**","IP":"::1"}
[2020-06-09 19:13:12] WF.DEBUG: After loading modalLoading.htm ... {"file:":"entryForm_v1.0.0.php","line#:":428,"session_id":"**ccbbhescjqevk02id43nf6tmgc**","IP":"::1"}
[2020-06-09 19:13:12] WF.DEBUG: Before loading shopping cart stuff ... {"file:":"entryForm_v1.0.0.php","line#:":438,"session_id":"**ccbbhescjqevk02id43nf6tmgc**","IP":"::1"}
[2020-06-09 19:13:12] WF.DEBUG: After loading shopping cart stuff ... {"file:":"entryForm_v1.0.0.php","line#:":449,"session_id":"**ccbbhescjqevk02id43nf6tmgc**","IP":"::1"}
[2020-06-09 19:13:12] WF.DEBUG: Before loading footer.htm ... {"file:":"entryForm_v1.0.0.php","line#:":459,"session_id":"**ccbbhescjqevk02id43nf6tmgc**","IP":"::1"}
[2020-06-09 19:13:12] WF.DEBUG: After loading footer.htm ... {"file:":"entryForm_v1.0.0.php","line#:":467,"session_id":"**ccbbhescjqevk02id43nf6tmgc**","IP":"::1"}
[2020-06-09 19:13:12] WF.DEBUG: Reading config settings and setting file includes {"file:":"setConfig.php","line#:":48,"$_SERVER[\"DOCUMENT_ROOT\"]":"/Users/Ross/Dropbox/htdocs/wantafest_mamp_pro/public_html","DB_SERVERNAME":"localhost","DB_NAME":"wantafest_contest_online","DB_SERVER_PORT":3311,"DB_USERNAME":"root","EMAIL_HOST":"mail.wonderfest.com","EMAIL_SMTP_AUTH":true,"EMAIL_USERNAME":"x.com","EMAIL_SMTP_SECURE":"tls","EMAIL_SERVER_PORT":587,"EMAIL_SEND_LOGS_TO":"y.com","EMAIL_SEND":false,"LOG_FLDR":"/Users/Ross/Dropbox/htdocs/wantafest_mamp_pro/private/contest/logs/","CACHE_FLDR":"/Users/Ross/Dropbox/htdocs/wantafest_mamp_pro/private/contest/cached-files","CACHE_EXPIRE_SQL_SEC":59,"CACHE_EXPIRE_PRINTOUT_SEC":360,"PHOTOS_FLDR":"/Users/Ross/Dropbox/htdocs/wantafest_mamp_pro/private/contest/photos/","BO_EXPIRE_SESSION_AFTER_SEC":900,"$entryFormCookieParams[\"lifetime\"]":1800,"$entryFormCookieParams[\"path\"]":"/","$entryFormCookieParams[\"domain\"]":".localhost","$entryFormCookieParams[\"secure\"]":false,"$entryFormCookieParams[\"httponly\"]":true,"PHP_SESSION_FLDR":"/Users/Ross/Dropbox/htdocs/wantafest_mamp_pro/sessions"}
[2020-06-09 19:13:12] WF.DEBUG: Session started or resumed - check session_id {"file:":"startSession.php","line#:":41,"session_id":"**vf7fgnu92up1uim9nlup1h8nlu**","session_name":"entry_form","Cookie lifetime":1800,"Cookie path":"/","Cookie domain":".localhost","Cookie secure":false,"Cookie httponly":true,"IP":"::1"}
[2020-06-09 19:13:12] WF.DEBUG: PHP version is 5.4.0 or greater {"file:":"startSession.php","line#:":65,"IP":"::1","phpversion()":"7.4.2","session_status()":2}
我在 macOS 10.14.6 上使用 MAMP Pro 5.7。我的 PHP 版本是 7.4.2
编辑根据@verjas 的建议,我将我的 favicon 移动到特定位置并更新了我的页面以使用它。我可以在浏览器选项卡中看到该图标,当我查看源代码时,我看到了这个:
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta name="robots" content="noindex,nofollow" />
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<link rel="shortcut icon" href="/contest/common/img/Favicon.png"/>
.
.
.
但是查看我的 Apache 错误日志,我看到了:
[Wed Jun 10 13:53:34 2020] [error] [client ::1] File does not exist: /Users/Ross/Dropbox/htdocs/wantafest_mamp_pro/public_html/favicon.ico, referer: http://want-a-fest:8888/contest/entry/entryForm.php
什么?我的页面不应该在 public_html 根目录中寻找它,并且文件名不同(应该是“Favicon.png”)。即使没有被引用,我是否必须在 public_html 中有一个“favicon.ico”?
解决方案
推荐阅读
- wordpress - 如何在wordpress的woo commerce中添加自定义权重设置?
- node.js - 尝试通过邮递员删除一行时,我收到此错误消息 id is not defined
- r - 将存储在列表中的数据帧保存到 R 中的单个文件中
- wordpress - 如何找到服务器频繁关闭的根本原因
- java - 将elasticsearch索引块标记为空的Java请求
- filter - Amplify GraphQL 查询过滤未按预期工作
- java - Jmeter:创建数组,然后在属性中设置,然后在数组中输入值
- c# - 如何检查该进程是否在 WCF c# 中终止
- c# - Ajax.BeginForm 完成时在 cshtml 中调用 ac# 函数
- vue.js - 在哪里放置应用程序中通用的 VueJS 组件