在很長一段時間內(nèi),PHP作為服務(wù)器端腳本語言的最大賣點之一就是會為從表單提交的值自動建立一個全局變量。在PHP 4.1中,PHP的制作者們推薦了一個訪問提交數(shù)據(jù)的 " /> 国产一二三四区中,国产伦精品一区三区视频,波多野结衣久久国产精品

一区二区久久-一区二区三区www-一区二区三区久久-一区二区三区久久精品-麻豆国产一区二区在线观看-麻豆国产视频

用PHP 4.2書寫安全的腳本

原著:Kevin Yank  轉(zhuǎn)自:www.linuxforum.NET (恭喜再此開通)

在很長一段時間內(nèi),php作為服務(wù)器端腳本語言的最大賣點之一就是會為從表單提交的值自動建立一個全局變量。在php 4.1中,php的制作者們推薦了一個訪問提交數(shù)據(jù)的替代手段。在php 4.2中,他們?nèi)∠四欠N老的做法!正如我將在這篇文章中解釋的那樣,作出這樣的變化的目的是出于安全性的考慮。我們將研究php在處理表單提交及其它數(shù)據(jù)時的新的做法,并說明為什么這樣做會提高代碼的安全性。 

這里有什么錯誤? 

看看下面的這段php腳本,它用來在輸入的用戶名及口令正確時授權(quán)訪問一個Web頁面: 
<?php 
// 檢查用戶名及口令 
if ($username == 'kevin' and $password == 'secret') 
$authorized = true; 
?> 
<?php if (!$authorized): ?> 
<!-- 未授權(quán)的用戶將在這里給予提示 --> 
<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內(nèi)容 --> 
<?php endif; ?> 
OK,我相信大約半數(shù)的讀者會不屑的說“太愚蠢了-- 我不會犯這樣的錯誤的!”但是我保證有很多的讀者會想“嗨,沒什么問題啊,我也會這么寫的!”當(dāng)然還會有少數(shù)人會對這個問題感到困惑(“什么是php?”)。php被設(shè)計為一個“好的而且容易的”腳本語言,初學(xué)者可以在很短的時間內(nèi)學(xué)會使用它;它也應(yīng)該能夠避免初學(xué)者犯上面的錯誤。 
再回到剛才的問題,上面的代碼中存在的問題是你可以很容易地獲得訪問的權(quán)力,而不需要提供正確的用戶名和口令。只在要你的瀏覽器的地址欄的最后添加?authorized=1。因為php會自動地為每一個提交的值創(chuàng)建一個變量 -- 不論是來自動一個提交的表單、URL查詢字符串還是一個cookie -- 這會將$authorized設(shè)置為1,這樣一個未授權(quán)的用戶也可以突破安全限制。 
那么,怎么簡單地解決這個問題呢?只要在程序的開頭將$authorized默認(rèn)設(shè)置為false。這個問題就不存在了!$authorized是一個完全在程序代碼中創(chuàng)建的變量;但是為什么開發(fā)者得為每一個惡意的用戶提交的變量擔(dān)心呢? 

php 4.2作了什么改變? 

php 4.2中,新安裝的php中的register_globals選項默認(rèn)為關(guān)閉,因此EGPCS值(EGPCS是Environment、Get、Post、Cookies、Server的縮寫 -- 這是php中外部變量來源的全部范圍)不會被作為全局變量來創(chuàng)建。當(dāng)然,這個選項還可以通過手工來開啟,但是php的開發(fā)者推薦你將其關(guān)閉。要貫徹他們的意圖,你需要使用其它的方法來獲取這些值。 
php 4.1開始,EGPCS值就可以從一組指定的數(shù)組中獲得: 
$_ENV -- 包含系統(tǒng)環(huán)境變量 
$_GET -- 包含查詢字符串中的變量,以及提交方法為GET的表單中的變量 
$_POST -- 包含提交方式為POST的表單中的變量 
$_COOKIE -- 包含所有cookie變量 
$_SERVER -- 包含服務(wù)器變量,例如HTTP_USER_AGENT 
$_REQUEST -- 包含$_GET、$_POST和$_COOKIE的全部內(nèi)容 
$_SESSION -- 包含所有已注冊的session變量 
php 4.1之前,當(dāng)開發(fā)者關(guān)閉register_globals選項(這也被考慮為提高php性能的一種方法)后,必須使用諸如$HTTP_GET_VARS這樣的令人討厭的名字來獲取這些變量。這些新的變量名不僅僅短,而且它們還有其他優(yōu)點。 
首先,讓我們在php 4.2中(也就是說關(guān)閉register_globals 選項)重寫上面提到的代碼: 
<?php 
$username = $_REQUEST['username']; 
$password = $_REQUEST['password']; 

// 檢查用戶名和口令 
if ($username == 'kevin' and $password == 'secret') 
$authorized = true; 
?> 
<?php if (!$authorized): ?> 
<!-- 未授權(quán)的用戶將在這里給予提示 --> 
<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內(nèi)容 --> 
<?php endif; ?> 
正如你看到的,我所需要做的只是在代碼的開始增加下面兩行: 
$username = $_REQUEST['username']; 
$password = $_REQUEST['password']; 
因為我們希望用戶名和密碼是由用戶提交的,所以我們從$_REQUEST數(shù)組中獲取這些值。使用這個數(shù)組使得用戶可以自由選擇傳遞方式:通過URL查詢字符串(例如允許用戶創(chuàng)建書簽時自動輸入他們的證書)、通過一個提交的表單或者是通過一個cookie。如果你想要限制只能通過表單提交證書(更精確地說,是通過HTTP POST請求),你可以使用$_POST數(shù)組: 
$username = $_POST['username']; 
$password = $_POST['password']; 
除了“引入”這兩個變量以外,程序代碼沒有任何改變。簡單地關(guān)閉register_globals選項促使開發(fā)者更進一步了解哪些數(shù)據(jù)是來自外部的(不可信任的)資源。 
請注意這里還有一個小問題:php中默認(rèn)的error_reporting設(shè)置仍然是E_ALL & ~E_NOTICE,因此如果“username”和“password”這兩個值沒有被提交,試圖從$_REQUEST數(shù)組或$_POST數(shù)組中獲得這兩個值并不會招致任何錯誤信息。如晨不你的php程序需要嚴(yán)格的錯誤檢查,你還需要增加一些代碼以首先檢查這些變量。 

但是這是不是意味著更多的輸入? 

是的,在象上面這樣的簡單程序中,使用php 4.2常常會增加輸入量。但是,還是看看光明的一面吧 -- 你的程序終究是更安全了! 
不過認(rèn)真的說,php的設(shè)計者并沒有完全忽視你的痛苦。在這些新數(shù)組中有一個特殊的其它所php變量都不具備的特征,它們是完全的全局變量。這對你有什么幫助呢?讓我們先對我們的示例進行一下擴充。 
為了使得站點中的多個頁面可以使用用戶名/口令論證,我們將我們用戶認(rèn)證程序?qū)懙揭粋€include文件(protectme.php)中: 
<?php /* protectme.php */ 
function authorize_user($authuser, $authpass) 

$username = $_POST['username']; 
$password = $_POST['password']; 
// 檢查用戶名和口令 
if ($username != $authuser or $password != $authpass): 
?> 
<!-- 未授權(quán)的用戶將在這里給予提示 --> 
<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; 

?> 
現(xiàn)在,我們剛才的頁面看上去將是這樣的: 
<?php 
require('protectme.php'); 
authorize_user('kevin','secret'); 
?> 
<!-- 有安全要求的HTML內(nèi)容 --> 
很簡單,很清晰明了,對不對?現(xiàn)在是考驗?zāi)愕难哿徒?jīng)驗的時候了 -- 在authorize_user 函數(shù)中少了什么? 
在函數(shù)中沒有申明$_POST是一個全局變量!在php 4.0中,當(dāng)register_globals開啟時,你需要增加一行代碼以在函數(shù)中獲取$username和$password變量: 
function authorize_user($authuser, $authpass) 

global $username, $password; 
... 
php中,和其它具有類似語法的語言不同,函數(shù)外的變量在函數(shù)中不能自動獲得,你需要象上面所說明的那樣增加一行以指定其來自global范圍。 
php 4.0中,當(dāng)關(guān)閉register_globals以提供安全性時,你可以使用$HTTP_POST_VARS數(shù)組以獲得你的表單提交的值,但是你還是需要從全局范圍導(dǎo)入這個數(shù)組: 
function authorize_user($authuser, $authpass) 

global $HTTP_POST_VARS; 
$username = $HTTP_POST_VARS['username']; 
$password = $HTTP_POST_VARS['password']; 
但是在php 4.1及以后的版本中,特殊的$_POST變量(以及上面提到的其它變量)可以在所有范圍內(nèi)使用。這就是不需要在函數(shù)中申明$_POST變量是一個全局變量的原因: 
function authorize_user($authuser, $authpass) 

$username = $_POST['username']; 
$password = $_POST['password']; 

這對session有什么影響? 

特殊的$_SESSION數(shù)組的引入實際上有助于簡化session代碼。你不需要將session變量申明為全局變量,然后再去留意哪些變量被注冊了,你現(xiàn)在可以簡單地從$_SESSION['varname']中引用你所有的session變量。 
現(xiàn)在讓我們來看看另一個用戶認(rèn)證的例子。這一次,我們使用sessions以標(biāo)志一個在你的網(wǎng)站繼續(xù)逗留的用戶已經(jīng)經(jīng)過了用戶認(rèn)證。首先,我們來看看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內(nèi)容 --> 
<?php endif; ?> 
和剛開始的程序一樣,這個程序也存在安全漏洞,在URL的最后加上?authorized=1可以繞過安全措施直接訪問頁面內(nèi)容。開發(fā)者可以將$authorized視為一個session變量而忽視了可以很容易地通過用戶輸入設(shè)置同樣的變量。 
當(dāng)我們增加了我們的特殊的數(shù)組(php 4.1)并關(guān)閉register_globals(php 4.2)后,我們的程序?qū)⑹沁@樣的: 
<?php 
session_start(); 
if ($username == 'kevin' and $password == 'secret') 
$_SESSION['authorized'] = true; 
?> 
<?php if (!$_SESSION['authorized']): ?> 
<!-- 顯示HTML表單以提示用戶登錄 --> 
<?php else: ?> 
<!-- 有安全要求的HTML內(nèi)容 --> 
<?php endif; ?> 
是不是更加簡單了?你不再需要再將普通的變量注冊為一個session變量,你只需要直接設(shè)置session變量(在$_SESSION數(shù)組中),然后用同樣的方法使用它。程序變得更短了,而且對于什么變量是session變量也不會引起混亂! 

總結(jié) 

在這篇文章中,我解釋了php腳本語言作出改變的深層原因。在php 4.1中,添加了一組特殊數(shù)據(jù)以訪問外部數(shù)據(jù)。這些數(shù)組可以在任何范圍內(nèi)調(diào)用,這使得外部數(shù)據(jù)的訪問更方便。在php 4.2中,register_globals被默認(rèn)關(guān)閉以鼓勵使用這些數(shù)組以避免無經(jīng)驗的開發(fā)者編寫出不安全的php代碼。 

php技術(shù)用PHP 4.2書寫安全的腳本,轉(zhuǎn)載需保留來源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 国产成人精品午夜在线播放 | 黄色免费网站在线 | 色77影院| 久久婷婷国产精品香蕉 | 婷婷免费在线 | 婷婷久久精品 | 欧美透逼 | 337p欧洲大胆扒开图片 | 色网站欧美 | 欧美性色综合网 | 91在线视频国产 | 久久国产偷 | 成人免费福利网站在线看 | 91精品日本久久久久久牛牛 | 色哟哟在线观看视频高清大全 | 91视频精品| 亚洲国产精品久久久天堂 | 大陆5g天天看天天爽免费 | 成人小视频在线播放 | 一二三四视频社区在线播放中国 | 亚洲日本一区二区三区在线不卡 | 色视频在线免费看 | 色婷婷天天综合在线 | 美女裸体自慰在线观看 | 91麻豆精品一二三区在线 | 在线观看免费视频网站色 | 五月国产综合视频在线观看 | 91精品导航在线网址免费 | 99久久香蕉国产综合影院 | 国产精品社区 | 中文字幕专区在线亚洲 | 精品国产91乱码一区二区三区 | 中国a毛片 | 日韩一区二区国色天香 | 好吊日在线观看 | 四虎精品免费永久在线 | 婷婷色爱区综合五月激情韩国 | 久久精品中文字幕有码日本 | 国产欧美一区二区三区在线看 | 亚洲网站在线播放 | 国产精品久久久久久 |