我有一个站点设置,在页面加载时,将所有用户提交的字符串转换为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
编辑.无论如何,你将不得不写下那个逃脱; 安全绳让你什么都没有.如果需要将字符串发送到其他目标格式,则需要使用不同的转义.
您无法将所有字符串处理问题封装到一个方便的框中,也不会再考虑它们; 这不是字符串的工作方式.
我知道这已被问过多年了,但是我发布了答案,因为上面的答案都没有向OP解释实际上是错的.
PHP使用内置serialize
和unserialize
方法序列化其会话.serialize
PHP能够序列化PHP对象(也就是类实例)并将它们转换为字符串.当你使用unserialize
这些字符串时,它会将这些字符串转换回那些相同的类.具有一些私有属性并希望对其进行编码/解码或在序列化/反序列化中执行复杂操作的Serializable
类实现类,并向类添加serialize
和unserialize
方法.
当PHP unserialize
尝试反序列化一个类对象,但没有声明/要求类名时,它不会发出警告或抛出一个Exception
,而是将其转换为一个对象__PHP_Incomplete_Class
.
如果您不希望将会话对象转换为__PHP_Incomplete_Class
,则可以通过在调用之前要求类文件session_start
或通过注册自动加载功能来执行此操作.
当您想要从变量中读取SafeString对象时,您只需要safestring.class.php
在调用之前包含它:session_start()
$_SESSION
是的,如果您正在使用(最有可能)
session_start()
内部调用的PHP框架,请require_once
事先确保您的类文件(使用钩子或框架提供的任何机制).