分享会全程 file_get_contents

Sharing session througout file_get_contents

美好的一天,我想使用 PHP 从我的服务器读取一个 PHP 执行文件(带有会话),但是一旦我通过传递会话 ID 调用 file_get_contents ,它不起作用:

为了检查,我在我的服务器上做了一个小测试,这里是 test_reader.php 文件:

session_start();

// if no test session, creating it & refreshing

if( !isset( $_SESSION['mysession'] ) ) {
    $_SESSION['mysession'] = 'hello world';
    header( 'Location: test_reader.php' );
}

// reading "test_readable.php"

$url = 'https://example.com/test_readable.php?';    

$parameters = http_build_query( array(
    'session' => session_id()
) );

$options = array( 'http' => array(
    'method'  => 'GET',
    'content' => $parameters
) );

$context = stream_context_create( $options );

echo ( $url.$parameters ).': <br>'.file_get_contents( ( $url.$parameters ), false, $context );

这里是 test_readable.php 文件:

// if session ID is sent, opening the session

if( isset( $_GET['session'] ) ) {
    session_id( $_GET['session'] );
}

session_start();

// checking result
    
if( isset( $_SESSION['mysession'] ) ) {
    echo 'yes';
} else {
    echo 'no (id: '.session_id().')';
}

if( isset( $_GET['session'] ) ) {
    echo ' but session ID found';
}

首先,在访问 test_reader.php 时加载它需要一分钟。

但除此之外,完全没有结果:

https://example.com/test_readable.php?session=x75277c2a8fccfcc4d446ec7c93d84006:

确实,test_readable.php 中的任何内容都没有打印出来。

所以我在 file_get_contents 结果上做了一个 var_dump 来检查响应:

bool(false)

而且我不明白为什么我的文件没有被读取?

您知道它是来自会话还是 file_get_contents 设置吗? 或者你知道它来自哪里吗?

预先感谢您的回复。

编辑 - 从头开始​​测试私人模式

test_reset.php

session_start();
$_SESSION['mysession'] = null;
unset( $_SESSION['mysession'] );
session_destroy();

test_readable.php

// if session ID is sent, opening the session

if( isset( $_GET['session'] ) ) {
    session_id( $_GET['session'] );
}

session_start();

// checking result

if( isset( $_SESSION['mysession'] ) ) {
    echo 'yes (id: '.session_id().')';
} else {
    echo 'no (id: '.session_id().')';
}

if( isset( $_GET['session'] ) ) {
    echo ' and session ID found';
}

test_reader.php

session_id( 'session'.rand( 1, 9 ).rand( 1, 9 ).rand( 1, 9 ) );
session_start();

echo '<div>'.session_id().'&nbsp;</div>';

$_SESSION['mysession'] = 'hello world';

$parameters = http_build_query( array(
    'session' => session_id()
) );

$options = array( 'http' => array(
    'method'  => 'GET',
    'content' => $parameters
) );

$context = stream_context_create( $options );

$url = 'https://example.com/test_readable.php?';

$read = file_get_contents( ( $url.$parameters ), false, $context );
// $read = file_get_contents( ( $url.$parameters ) );

echo '<div>'.( $url.$parameters ).'&nbsp;</div>';

echo '<div>'.$read.'&nbsp;</div>';

var_dump( $read );

测试轨迹:

https://example.com/test_reset.php
>> <empty page>

https://example.com/test_readable.php
>> no (id: 59081a4dfd8ea3acd10ebaafd432daaf)

https://example.com/test_reader.php
>> session432 
>> https://example.com/test_readable.php?session=session432 
>> 
>> bool(false)

(如果我不将 file_get_content 与上下文一起使用,结果相同)。

编辑 2 - 没有上下文的测试/已解决

我没有更改其他文件,只更改了以下文件:

test_reader.php

session_id( 'session'.rand( 1, 9 ).rand( 1, 9 ).rand( 1, 9 ) );
session_start();

$sessionID = session_id();
echo '<div>'.$sessionID.'&nbsp;</div>';

$_SESSION['mysession'] = 'hello world';
session_write_close();

$parameters = http_build_query( array(
    'session' => $sessionID
) );

$url = 'https://example.com/test_readable.php?';

$read = file_get_contents( ( $url.$parameters ) );

echo '<div>'.( $url.$parameters ).'&nbsp;</div>';

echo '<div>'.$read.'&nbsp;</div>';

var_dump( $read );

结果是:

https://example.com/test_readable.php
>> no (id: 2d3b1d3e9d2975134bf3141d3c49c3d8)

https://example.com/test_reader.php
>> session849 
>> https://example.com/test_readable.php? 
>> no (id: ce844dd021a0e1d167a316a2e4cd08a0) 
>> string(41) "no (id: ce844dd021a0e1d167a316a2e4cd08a0)"

确保你销毁了第一个会话使用这个:

 
session_abort(); // add this line

// set the new session
session_id( $_GET['session'] );

session_start();

// checking result
    
if( isset( $_SESSION['mysession'] ) ) {
    echo 'yes';
} else {
    echo 'no (id: '.session_id().')';
}

if( isset( $_GET['session'] ) ) {
    echo ' but session ID found';
}

流上下文的使用在这里毫无意义。 content 指定要作为请求正文发送的内容 - 但 GET 请求不会在正文中发送它们的数据。您应该完全删除流上下文,然后简单地将您的参数附加到 URL.

并且在使用 file-based 会话存储时,PHP 锁定会话文件,只要一个脚本实例仍在“使用”它。因此,如果您在发出请求之前调用 session_write_close,那么尝试在向另一个应该使用同一会话的脚本发出请求的同一脚本中设置会话值只会正常工作。这会将所有会话更改写入磁盘,然后释放对会话文件的锁定。