PHP 5.6から7にアップグレードし、カスタムセッションハンドラスクリプトを使用してデータベース内のセッションを管理し、ユーザをより適切に管理できるようにしました。 1つのことを除いて、すべてが以前と同じように機能します。PHP 7 session_regenerate_idメンバ関数への失敗とPDO呼び出しnullの場合prepare()null
session_regenerate_id(true);
ユーザーが正常にログインした後、セッション固定を回避するために、session_regenerate_idを呼び出します。
[14-May-2016 02:04:07 UTC] PHP Warning: Uncaught Error: Call to a member function prepare() on null in /home/xxxx/protected/class.database.php:38 Stack trace:
#0 /home/xxxx/protected/class.session.php(37): Database->query('SELECT data FRO...')
#1 [internal function]: Session->_read('kuq04akaagkjd5n...')
#2 /home/xxxx/protected/user_auth_fns.php(705): session_regenerate_id(true)
#3 /home/xxxx/public_html/passengersdir/login.php(42): login_user('xxxx', 'xxxx', 'xxxx', NULL)
#4 {main}
thrown in /home/xxxx/protected/class.database.php on line 38 [14-May-2016 02:04:07 UTC] Recoverable error: session_regenerate_id(): Failed to create(read) session ID: user (path:) in /home/xxxx/protected/user_auth_fns.php on line 705
どうやらsession_regenerateはfalseを返しますが、PHPは5.6、それはスライドさせてみましょう:PHP 7ではないので、PHP 5.6でうまくいきました。これはPHPからの正式な返答です。
- PHP 7.0以降では、ユーザセーブハンドラからのバグの返り値を許可していません。 ユーザー読み取りハンドラは常に成功のために "文字列"データを返さなければなりません。
- ネイティブ・セーブ・ハンドラは、存在しないセッション・データを含む成功したケースでは、SUCCESSを戻す必要があります。
FALSE
/failureは、permission/network/etcエラーなどの「読み込みに誤りがあります」を意味します。
https://bugs.php.net/bug.php?id=71187
一部の人々はここに回避策を見つけました:私は回避策を好きではない https://github.com/magento/magento2/issues/2827
It appears to be an issue with the read function not always returning a string. As a temporary fix I cast the return value for the read() function in the SessionHandler as a string.
。私は単にsession_generate_id
を取り除くことができます。これは古き良き時代のように機能しますが、セッションの固定を開くことができます。
理想的には、この問題を解決するか、ログインに成功した後でセッションの固定を防ぐためのより良い方法を探したいと考えています。見ていただきありがとうございます。ここで
は、問題のコードです:
public function __construct(){ // this is class.database.php
// Set DSN
$dsn = 'mysql:host=' . $this->host . ';dbname=' . $this->dbname;
// Set options
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
// Create a new PDO instanace
try{
$this->dbh = new PDO($dsn, $this->user, $this->pass, $options);
}
// Catch any errors
catch(PDOException $e){
$this->error = $e->getMessage();
}
}
public function query($query){
// this throws Uncaught Error: Call to a member function prepare() on null in /home/opentaxi/protected/class.database.php:38
$this->stmt = $this->dbh->prepare($query);
}
public function bind($param, $value, $type = null){
if (is_null($type)) {
switch (true) {
case is_int($value):
$type = PDO::PARAM_INT;
break;
case is_bool($value):
$type = PDO::PARAM_BOOL;
break;
case is_null($value):
$type = PDO::PARAM_NULL;
break;
default:
$type = PDO::PARAM_STR;
}
}
$this->stmt->bindValue($param, $value, $type);
}
public function execute(){
return $this->stmt->execute();
}
// this is from class.session.php
public function _read($id){
//this is /home/opentaxi/protected/class.session.php(37): Database->query('SELECT data FRO...')
$this->db->query('SELECT data FROM sessions WHERE id = :id');
$this->db->bind(':id', $id);
if($this->db->execute()){
$row = $this->db->single();
return (string)$row['data']; // I have the workaround that's not working!
}else{
return '';
}
}
*** "ここには問題のコードがあります:" ***私は 'session_generate_id'を表示していません。 –