无法从外部页面访问Drupal $ _SESSION变量

时间:2012-11-11 02:27:12

标签: php session drupal drupal-7 session-variables

我在外部网页上访问$ _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,因此它找不到它。

为什么我没有使用登录用户的会话?

修改

不确定为什么会这样,但只要两个外部文件位于不同的目录中,这样就可以了。如果它们位于同一目录中,则似乎启动新会话而不访问现有会话。不知道为什么。

2 个答案:

答案 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'];