ページの読み込み時に、ユーザーが送信したすべての文字列をSafeStringオブジェクトに変換するサイトのセットアップがあります。 SafeStringに不慣れな人のために、基本的にはユーザーにサニタイズされたデータをエコーアウトさせ、XSSなどを阻止します。
とにかく、問題があります。 $ _SESSION配列に__PHP_Incomplete_Class Object
が入力されています。私が読んだことから、これはセッションの前にクラスを初期化せず、クラスオブジェクトをセッションに保存しないためです。
私のコードは次のとおりです。
require_once __WEBROOT__ . '/includes/safestring.class.php';
$temp = array
(
&$_SERVER, &$_GET, &$_POST, &$_COOKIE,
&$_SESSION, &$_ENV, &$_REQUEST, &$_FILES,
&$HTTP_SERVER_VARS, &$HTTP_GET_VARS,
&$HTTP_POST_VARS, &$HTTP_COOKIE_VARS,
&$HTTP_POST_FILES, &$HTTP_ENV_VARS
);
function StringsToSafeString(&$array)
{
foreach ($array as $key => $value)
{
if (is_string($array[$key]))
{
$array[$key] = new SafeString($value);
}
if (is_array($array[$key]))
{
StringsToSafeString($array[$key]);
}
}
}
StringsToSafeString($temp);
unset($temp);
問題を解決するこれを書き換える方法を考えることはできません:/
何か案は?
$_SESSION
にアクセスしているときは、現在のスクリプトのセッションから読み取ったデータのコピーを変更するだけでなく、SafeStringオブジェクトをアクティブなセッションに書き戻します。
しかし、セッションにカスタムオブジェクトを置くことは危険であり、私は一般的に避けようとするものです。それを行うには、session_start
を呼び出す前に問題のクラスを定義しておく必要があります。そうしないと、PHPのセッションハンドラーはそのクラスのインスタンスを逆シリアル化する方法を認識できず、__PHP_Incomplete_Class Object
になります。
そのため、セッションをフロビングすることは避けてください。このアプローチを取る必要がある場合は、$_SESSION
からローカル$mysession
配列にデータのコピーを作成します。ただし、SafeStringの考え全体は危険で実行不可能だと思います。このアプローチが水密になるとは思わない。未加工テキストの文字列が「安全」であるかどうかは、それがどこから来たのかとは関係なく、ターゲットコンテキスト用にエンコードする方法のプロパティです。
データベースやファイルなどの異なるソースから別のテキスト文字列を取得する場合、またはスクリプト自体で計算する場合、ユーザーからの文字列とまったく同じ処理が必要です。htmlspecialchars
である必要があります編とにかくそのエスケープを書く必要があります。セーフストリングは何も得ません。文字列を別の宛先形式に送信する必要がある場合は、別のエスケープが必要になります。
すべての文字列処理の問題を1つの便利なボックスにカプセル化することはできません。それは文字列の仕組みではありません。
これが尋ねられてから何年も経ちますが、上記の回答はどれも実際にOPに実際に間違っていることを説明していないため、回答を投稿しています。
PHPは、組み込みの serialize
および unserialize
メソッドを使用してセッションをシリアル化します。 serialize
of PHPには、PHPオブジェクト(別名クラスインスタンス)をシリアル化し、文字列に変換する機能があります。これらの文字列を unserialize
すると、それらの値を持つ同じクラスに変換されます。いくつかのプライベートプロパティがあり、それをエンコード/デコードするか、シリアライズ/デシリアライズで複雑な処理を行うクラスは、 Serializable
クラスを実装し、 serialize
および unserialize
メソッドをクラスに追加します。
PHPの unserialize
がクラスオブジェクトのシリアル化を解除しようとしたが、クラス名が宣言/要求されず、警告を出すか Exception
、それを__PHP_Incomplete_Class
のオブジェクトに変換します。
セッションオブジェクトを__PHP_Incomplete_Class
に変換したくない場合は、 session_start
を呼び出す前にクラスファイルを要求するか、オートロード機能を登録します。
_safestring.class.php
_変数からSafeStringオブジェクトを読み取る場合は、session_start()
を呼び出す前に_$_SESSION
_を含める必要があります。
_<?php
require_once __WEBROOT__ . '/includes/safestring.class.php';
session_start();
print_r($_SESSION);
_
ええ、もしPHPフレームワーク(おそらく)を内部的にsession_start()
を呼び出すフレームワークを使用している場合は、事前にクラスファイル_require_once
_フレームワークが提供するメカニズム)。
ルクマンの答えは正しい。しかし、あなたはすでにあなたの質問でそれを言及しているので、どういうわけか、セッションが始まる前にクラスをインスタンス化することはできないようです。
Php configでセッションが自動的に開始するかどうかを確認できます。 http://www.php.net/manual/en/session.configuration.php#ini.session.auto-start
もしそれらが助けにならないなら、その前にクラスをオートロードできるかどうかチェックしたいかもしれません: http://php.net/manual/en/language.oop5.autoload.php =
他のすべてが失敗した場合でも、セッションに保存する前にオブジェクトをシリアル化して、オブジェクトを取得するたびにシリアル化を解除できます。 http://php.net/manual/en/function.serialize.php
私はあなたのコードに変数を保存する場所を見ませんが、それは次のようなものになります
$mystuff = unserialize($_SESSION["mystuff"]);
$mystuff->dostuff();
$_SESSION["mystuff"] = serialize($mystuff);
変数をシリアル化解除する前に、クラス定義を必ずロードしてください
$ 2c、*-パイク
私はこのようなものを扱っただけです。私の注文がどのようにねじ込まれたかを最終的に見つけるために何時間もかかった。
非同期で呼び出されるファイルがありました。
myFile.php
そのファイルには次のものが含まれていました。
$result = include ("myOtherFile.php");
return $result;
Myotherfile.phpには次のようなものがあります
require_once "lib/myClassLibs.php";
require_once "webconfig.php";
webconfig.phpにはsession_start()呼び出しが含まれていました。
Lib/myClassLibsには、すべてのクラス情報の初期化があります。 webconfig呼び出しの前に確認すると、クラスが利用可能であることがわかります。
Webconfig呼び出しの前に確認すると、セッションが既に開始されていることもわかります。 lib/myClassLibs.phpの前にチェックすると、セッションがすでに開始されていることがわかります。
MyOtherFile.phpをインクルードする前にmyFile.phpをチェックすると、セッションが開始されていません。
これは、私が気にせずに過去8年間機能してきたレガシーコードを表しています。 「MyOtherFile.php」からインクルードを取り出しました。現在、私のセッションは適切に同期しています。
json_encode
およびjson_decode
関数を使用して問題を解決しました。
これは、セッションに値を割り当てたい場所です。
$user_json = json_encode($user);
$_SESSION['user'] = $user_json;
これは、jsonをデコードした後にユーザーに表示する場所です
session_start();
$user_json= $_SESSION['user'];
$user = json_decode($user_json);
これで問題は解決しましたが、パフォーマンスやセキュリティについてはわかりません。私はそれらをチェックしていません。
Phpファイルの先頭に __ autoload 関数を含めることで、この問題を解決しました。そのため、次のようになります。
<?php
require_once("path/to/include.inc");
//Needed for serialization/deserialization
function __autoload($class_name) {
include "path/to/". $class_name . '.php';
}
PHP 5では、この関数は必要ありませんが、この関数を使用するまで行き詰まりました。
これは非常に古い質問ですが、この問題に遭遇しました。さらに調査と実験を重ねた結果、セッションにクラスを保存するのに受け入れられる代替案だと思いました。それは少しハックかもしれませんが、私の現在のプロジェクトで動作します。
注:この回避策は、ユーザーがログインしたときにセッションを開始し、ユーザーがセッション中に遭遇する可能性のあるすべてのクラスを含めたくないため、私にとってはうまくいきます。すべてのクラスを含めることは実用的でも効率的でもないようです(しかし、これはこれ以上良いことではないかもしれません???)。
まず、基本クラスには、特定の配列からオブジェクト属性を自動的に取り込む次のコードが含まれています。
class BaseClass {
public function __construct($properties=[]){
if (!empty($properties)) {
array_walk($properties, function ($val, $key) {
$this->fromArray($key, $val);
});
}
}
public function fromArray($property, $value){
return (property_exists($this, $property)) ? $this->$property = $value : null;
}
public function toArray(){
return get_object_vars($this);
}
}
回避策: toArray()メソッドを使用して、クラスインスタンスをセッションに移動する前に配列に変換し、セッションから取得するときにクラスの新しいインスタンスを作成します。
$_SESSION['user'] = $userInstance->toArray();
// ... do stuff ...
$userInstance = new User($_SESSION['user']);
これは、クラスをデータベースに書き込み、JSONに変換する場合にも非常に便利です。 PHP配列を使用すると、どちらも簡単になります。
上で言ったように、これはこの問題を処理する最も効率的な方法かもしれませんし、そうでないかもしれません。また、「配列に変換するだけなら、PHPクラスを使用する必要がありますか?」
ここでの私の間違いは、session.auto_start
をon
に設定します。セッションは、コード行(オートローダーを含む)が呼び出される前に初期化されます。
私は同じ問題に遭遇し、解決策は@bobinceの答えに触発されました
それを行うには、session_startを呼び出す前に問題のクラスを定義しておく必要があります
まず、私のセッションは次のように設定されました。
_$_SESSION["customer"] = $customerObj;
_
次に、session_start()
を呼び出す前に、まずクラスをインポートしてクラスをロードまたは定義し、その後すぐにsession_start()
を呼び出す必要があります
_require 'entity/Customer.php';
ob_start();
session_start();
$customer = new Customer();
if (isset($_SESSION["customer"]))
{
$customer = $_SESSION["customer"];
echo $customer->getCustomerName();
}
_