服务器 Register_Globals 关闭 会影响什么功能

服务器 Register_Globals 关闭 会影响什么功能

_globals使用详解
register_globals是php.ini里的一个配置,这个配置影响到php如何接收传递过来的参数,如果你的问题是:为什么我的表单无法传递数据?为什么我的程序无法得到传递过来的变量?等等,那么你需要仔细的阅读以下的内容。

register_globals的值可以设置为:On或者Off,我们举一段代码来分别描述它们的不同。

代码:

<form name="frmTest" id="frmTest" action="URL">
<input type="text" name="user_name" id="user_name">
<input type="password" name="user_pass" id="user_pass">
<input type="submit" value="login">
</form>

 

当register_globals=Off的时候,下一个程序接收的时候应该用$_GET['user_name']和$_GET['user_pass']来接受传递过来的值。(注:当<form>的method属性为post的时候应该用$_POST['user_name']和$_POST['user_pass'])

当register_globals=On的时候,下一个程序可以直接使用$user_name和$user_pass来接受值。

顾名思义,register_globals的意思就是注册为全局变量,所以当On的时候,传递过来的值会被直接的注册为全局变量直接使用,而Off的时候,我们需要到特定的数组里去得到它。所以,碰到上边那些无法得到值的问题的朋友应该首先检查一下你的register_globals的设置和你获取值的方法是否匹配。(查看可以用phpinfo()函数或者直接查看php.ini)

那我们为什么要使用Off呢?原因有2:
1、php以后的新版本默认都用Off,虽然你可以设置它为On,但是当你无法控制服务器的时候,你的代码的兼容性就成为一个大问题,所以,你最好从现在就开始用Off的风格开始编程
2、这里有两篇文章介绍为什么要Off而不用On
http://www.linuxforum.net/forum/gshowflat.php?Cat=&Board=php3&Number=292803&page=0&view=collapsed&sb=5&o=all&fpart=
http://www.php.net/manual/en/security.registerglobals.php

现在还有一个问题就是,以前用On风格写的大量脚本怎么办?
如果你以前的脚本规划得好,有个公共包含文件,比如config.inc.php一类的文件,在这个文件里加上以下的代码来模拟一下(这个代码不保证100%可以解决你的问题,因为我没有大量测试,但是我觉得效果不错)。

代码:

<?php
if ( !ini_get('register_globals') )
{
extract($_POST);
extract($_GET);
extract($_SERVER);
extract($_FILES);
extract($_ENV);
extract($_COOKIE);

if ( isset($_SESSION) )
{
extract($_SESSION);
}
}
?>

register_globals = Off的情况不仅仅影响到如何获取从<form>、url传递过来的数据,也影响到session、cookie,对应的,得到session、cookie的方式应该为:$_SESSION[]、$_COOKIE。同时对于session的处理也有一些改变,比如,session_register()没有必要而且失效,具体的变化,请查看php manual里的Session handling functions

$_REQUEST中间的内容实际上还是来源于$_GET $_POST $_COOKIE,缺点是无法判断变量到底来自于get post 还是cookie,对要求比较严格的场合不适用。
php manual 写到:

Variables provided to the script via the GET, POST, and COOKIE input mechanisms, and which therefore cannot be trusted. The presence and order of variable inclusion in this array is defined according to the PHP variables_order configuration directive.

在PHP 4.2中,新安装的PHP中的register_globals选项默认为关闭,因此EGPCS值(EGPCS是Environment、Get、Post、Cookies、Server的缩写 -- 这是PHP中外部变量来源的全部范围)不会被作为全局变量来创建。当然,这个选项还可以通过手工来开启,但是PHP的开发者推荐你将其关闭。要贯彻他们的意图,你需要使用其它的方法来获取这些值。
从PHP 4.1开始,EGPCS值就可以从一组指定的数组中获得:
$_ENV -- 包含系统环境变量
$_GET -- 包含查询字符串中的变量,以及提交方法为GET的表单中的变量
$_POST -- 包含提交方式为POST的表单中的变量
$_COOKIE -- 包含所有cookie变量
$_SERVER -- 包含服务器变量,例如HTTP_USER_AGENT
$_REQUEST -- 包含$_GET、$_POST和$_COOKIE的全部内容
$_SESSION -- 包含所有已注册的session变量
在PHP 4.1之前,当开发者关闭register_globals选项(这也被考虑为提高PHP性能的一种方法)后,必须使用诸如$HTTP_GET_VARS这样的令人讨厌的名字来获取这些变量。这些新的变量名不仅仅短,而且它们还有其他优点。
首先,让我们在PHP 4.2中(也就是说关闭register_globals 选项)重写上面提到的代码:
<?php
$username = $_REQUEST['username'];
$password = $_REQUEST['password'];

// 检查用户名和口令
if ($username == 'kevin' and $password == 'secret')
$authorized = true;
?>
<?php if (!$authorized): ?>
<!-- 未授权的用户将在这里给予提示 -->
<p>Please enter your username and password:</p>
<form action="<?=$PHP_SELF?>" method="POST">
<p>Username: <input type="text" name="username" /><br />
Password: <input type="password" name="password" /><br />
<input type="submit" /></p>
</form>
<?php else: ?>
<!-- 有安全要求的HTML内容 -->
<?php endif; ?>
正如你看到的,我所需要做的只是在代码的开始增加下面两行:
$username = $_REQUEST['username'];
$password = $_REQUEST['password'];
因为我们希望用户名和密码是由用户提交的,所以我们从$_REQUEST数组中获取这些值。使用这个数组使得用户可以自由选择传递方式:通过URL查询字符串(例如允许用户创建书签时自动输入他们的证书)、通过一个提交的表单或者是通过一个cookie。如果你想要限制只能通过表单提交证书(更精确地说,是通过HTTP POST请求),你可以使用$_POST数组:
$username = $_POST['username'];
$password = $_POST['password'];
除了“引入”这两个变量以外,程序代码没有任何改变。简单地关闭register_globals选项促使开发者更进一步了解哪些数据是来自外部的(不可信任的)资源。
请注意这里还有一个小问题:PHP中默认的error_reporting设置仍然是E_ALL & ~E_NOTICE,因此如果“username”和“password”这两个值没有被提交,试图从$_REQUEST数组或$_POST数组中获得这两个值并不会招致任何错误信息。如晨不你的PHP程序需要严格的错误检查,你还需要增加一些代码以首先检查这些变量。

但是这是不是意味着更多的输入?

是的,在象上面这样的简单程序中,使用PHP 4.2常常会增加输入量。但是,还是看看光明的一面吧 -- 你的程序终究是更安全了!
不过认真的说,PHP的设计者并没有完全忽视你的痛苦。在这些新数组中有一个特殊的其它所PHP变量都不具备的特征,它们是完全的全局变量。这对你有什么帮助呢?让我们先对我们的示例进行一下扩充。
为了使得站点中的多个页面可以使用用户名/口令论证,我们将我们用户认证程序写到一个include文件(protectme.php)中:
<
?php /* protectme.php */
function authorize_user($authuser, $authpass)
{
$username = $_POST['username'];
$password = $_POST['password'];
// 检查用户名和口令
if ($username != $authuser or $password != $authpass):
?>
<!-- 未授权的用户将在这里给予提示 -->
<p>Please enter your username and password:</p>
<form action="<?=$PHP_SELF?>" method="POST">
<p>Username: <input type="text" name="username" /><br />
Password: <input type="password" name="password" /><br />
<input type="submit" /></p>
</form>
<?php
exit();
endif;
}
?>
现在,我们刚才的页面看上去将是这样的:
<?php
require('protectme.php');
authorize_user('kevin','secret');
?>
<!-- 有安全要求的HTML内容 -->
很简单,很清晰明了,对不对?现在是考验你的眼力和经验的时候了 -- 在authorize_user 函数中少了什么?
在函数中没有申明$_POST是一个全局变量!在php 4.0中,当register_globals开启时,你需要增加一行代码以在函数中获取$username和$password变量:
function authorize_user($authuser, $authpass)
{
global $username, $password;
...
在PHP中,和其它具有类似语法的语言不同,函数外的变量在函数中不能自动获得,你需要象上面所说明的那样增加一行以指定其来自global范围。
在PHP 4.0中,当关闭register_globals以提供安全性时,你可以使用$HTTP_POST_VARS数组以获得你的表单提交的值,但是你还是需要从全局范围导入这个数组:
function authorize_user($authuser, $authpass)
{
global $HTTP_POST_VARS;
$username = $HTTP_POST_VARS['username'];
$password = $HTTP_POST_VARS['password'];
但是在PHP 4.1及以后的版本中,特殊的$_POST变量(以及上面提到的其它变量)可以在所有范围内使用。这就是不需要在函数中申明$_POST变量是一个全局变量的原因:
function authorize_user($authuser, $authpass)
{
$username = $_POST['username'];
$password = $_POST['password'];

这对session有什么影响?

特殊的$_SESSION数组的引入实际上有助于简化session代码。你不需要将session变量申明为全局变量,然后再去留意哪些变量被注册了,你现在可以简单地从$_SESSION['varname']中引用你所有的session变量。
现在让我们来看看另一个用户认证的例子。这一次,我们使用sessions以标志一个在你的网站继续逗留的用户已经经过了用户认证。首先,我们来看看PHP 4.0版本(开启register_globals):
<?php
session_start();
if ($username == 'kevin' and $password == 'secret')
{
$authorized = true;
session_register('authorized');
}
?>
<?php if (!$authorized): ?>
<!-- 显示HTML表单以提示用户登录 -->
<?php else: ?>
<!-- 有安全要求的HTML内容 -->
<?php endif; ?>
和刚开始的程序一样,这个程序也存在安全漏洞,在URL的最后加上?authorized=1可以绕过安全措施直接访问页面内容。开发者可以将$authorized视为一个session变量而忽视了可以很容易地通过用户输入设置同样的变量。
当我们增加了我们的特殊的数组(PHP 4.1)并关闭register_globals(PHP 4.2)后,我们的程序将是这样的:
<?php
session_start();
if ($username == 'kevin' and $password == 'secret')
$_SESSION['authorized'] = true;
?>
<?php if (!$_SESSION['authorized']): ?>
<!-- 显示HTML表单以提示用户登录 -->
<?php else: ?>
<!-- 有安全要求的HTML内容 -->
<?php endif; ?>
是不是更加简单了?你不再需要再将普通的变量注册为一个session变量,你只需要直接设置session变量(在$_SESSION数组中),然后用同样的方法使用它。程序变得更短了,而且对于什么变量是session变量也不会引起混乱!

总结

在这篇文章中,我解释了PHP脚本语言作出改变的深层原因。在PHP 4.1中,添加了一组特殊数据以访问外部数据。这些数组可以在任何范围内调用,这使得外部数据的访问更方便。在PHP 4.2中,register_globals被默认关闭以鼓励使用这些数组以避免无经验的开发者编写出不安全的PHP代码。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据