1

我无法访问外部页面上的 $_SESSION 变量。

基本上,我在一个drupal节点上有一个表单,当提交时,它会发布到一个外部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,因此它找不到。

任何想法为什么我不使用登录用户的会话?

编辑

不知道为什么会这样,但是只要两个外部文件位于不同的目录中,就可以正常工作。如果它们在同一目录中,则似乎开始了一个新会话而不访问现有会话。不知道为什么。

4

2 回答 2

2

如果我理解正确,您将来自 Drupal 的表单(其中有经过身份验证的用户)提交到外部 PHP 文件。当您尝试从引导 Drupal 的外部页面访问会话时,会话不包含先前保存的值,并且用户被报告为匿名用户,而不是先前提交表单的经过身份验证的用户。

这通常发生,因为:

  • Drupal 找不到名称为session_name()和的 cookie substr(session_name(), 1)
    在这种情况下,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传递给其会话读取回调(_drupal_session_read())的参数值相等的 sid(或 ssid)的记录。如果会话已过期,也可能发生这种情况。

    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();
    }
于 2012-11-11T17:15:27.663 回答
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'];
于 2014-03-22T20:42:39.763 回答