我在外部网页上访问$ _SESSION变量时遇到问题。
基本上,我在drupal节点上有一个表单,在提交时,POSTS到外部php文件,它将值保存到$ _SESSION变量,如下所示:
//Bootstrap Drupal so we can use the SESSION variables, where we store the calling number for the
//duration of the logged in session
define('DRUPAL_ROOT', $_SERVER['DOCUMENT_ROOT']);
$base_url = 'http://'.$_SERVER['HTTP_HOST'];
require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_SESSION);
//Save number as the calling number for the session
$_SESSION['calling-number']=$_REQUEST['calling-number'];
工作正常。
当我稍后尝试使用:
从外部页面访问$ _SESSION变量时//Bootstrap Drupal so we can use the SESSION variables, where we store the calling number for the
//duration of the logged in session
define('DRUPAL_ROOT', $_SERVER['DOCUMENT_ROOT']);
$base_url = 'http://'.$_SERVER['HTTP_HOST'];
require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_SESSION);
echo $_SESSION['calling-number'];
我一无所获。如果我在这个新页面上查看$ user,我可以看到它是因为它在匿名用户会话(uid = 0)下运行,而不是设置$ _SESSION变量的登录用户ID,因此它找不到它。
为什么我没有使用登录用户的会话?
修改
不确定为什么会这样,但只要两个外部文件位于不同的目录中,这样就可以了。如果它们位于同一目录中,则似乎启动新会话而不访问现有会话。不知道为什么。
答案 0 :(得分:2)
如果我理解正确,您可以从Drupal(其中有经过身份验证的用户)向外部PHP文件提交表单。当您尝试从引导Drupal的外部页面访问会话时,会话不包含先前保存的值,并且报告用户是匿名用户,而不是先前提交表单的经过身份验证的用户。
这通常是因为:
Drupal找不到名称为session_name()
和substr(session_name(), 1)
的Cookie。
在这种情况下,drupal_session_initialize()执行以下代码。
// Set a session identifier for this request. This is necessary because
// we lazily start sessions at the end of this request, and some
// processes (like drupal_get_token()) needs to know the future
// session ID in advance.
$GLOBALS['lazy_session'] = TRUE;
$user = drupal_anonymous_user();
// Less random sessions (which are much faster to generate) are used for
// anonymous users than are generated in drupal_session_regenerate() when
// a user becomes authenticated.
session_id(drupal_hash_base64(uniqid(mt_rand(), TRUE)));
if ($is_https && variable_get('https', FALSE)) {
$insecure_session_name = substr(session_name(), 1);
$session_id = drupal_hash_base64(uniqid(mt_rand(), TRUE));
$_COOKIE[$insecure_session_name] = $session_id;
}
Drupal在其会话数据库表中找不到sid(或ssid)的记录,该记录等于传递给其会话读回调(_drupal_session_read())的$sid
参数的值。如果会话已过期,也可能发生这种情况。
if ($is_https) {
$user = db_query("SELECT u.*, s.* FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.ssid = :ssid", array(':ssid' => $sid))->fetchObject();
if (!$user) {
if (isset($_COOKIE[$insecure_session_name])) {
$user = db_query("SELECT u.*, s.* FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.sid = :sid AND s.uid = 0", array(
':sid' => $_COOKIE[$insecure_session_name],
))
->fetchObject();
}
}
}
else {
$user = db_query("SELECT u.*, s.* FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.sid = :sid", array(':sid' => $sid))->fetchObject();
}
当PHP关闭时,Drupal始终通过_drupal_session_write()保存当前用户的会话。当当前用户是匿名用户时也会这样做。
if (!drupal_save_session()) {
// We don't have anything to do if we are not allowed to save the session.
return;
}
// Check whether $_SESSION has been changed in this request.
$last_read = &drupal_static('drupal_session_last_read');
$is_changed = !isset($last_read) || $last_read['sid'] != $sid || $last_read['value'] !== $value;
// For performance reasons, do not update the sessions table, unless
// $_SESSION has changed or more than 180 has passed since the last update.
if ($is_changed || !isset($user->timestamp) || REQUEST_TIME - $user->timestamp > variable_get('session_write_interval', 180)) {
// Either ssid or sid or both will be added from $key below.
$fields = array(
'uid' => $user->uid,
'cache' => isset($user->cache) ? $user->cache : 0,
'hostname' => ip_address(),
'session' => $value,
'timestamp' => REQUEST_TIME,
);
// Use the session ID as 'sid' and an empty string as 'ssid' by default.
// _drupal_session_read() does not allow empty strings so that's a safe
// default.
$key = array(
'sid' => $sid,
'ssid' => '',
);
// ...
db_merge('sessions')
->key($key)
->fields($fields)
->execute();
}
答案 1 :(得分:1)
对于那些在使用外部网页时遇到同样问题的人:
您只需要在代码中添加一些参数
事实上,你必须精确你的drupal目录。
实施例。对于位于drupal目录之前的目录中的页面
// Definine the path to "DRUPAL_ROOT" which is used throughout bootstrap.inc
define('DRUPAL_ROOT', getcwd() . '/your_drupal_directory');
// you could write like this too
// define('DRUPAL_ROOT', $_SERVER['DOCUMENT_ROOT'] . '/your_drupal_directory');
// Define the $base_url which will be used by Drupal to make sure we are on the same domain
$base_url = 'http://'.$_SERVER['HTTP_HOST']. '/your_drupal_directory';
require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_SESSION);
echo $_SESSION['calling-number'];