用PHP模擬HTTP中的POST請求JSP網頁,提交資料
今天我們來實現一個提交話費的WEB程式,主要應用在:代理電信公司話費交納。
第一步:獲取登入頁面的SESSION會話ID值.
為什麼要獲取SESSION值?
我們知道,使用者訪問一個網站時往往需要瀏覽許多網頁。對於一個通過PHP構築的網站來說,使用者在訪問的過程中需要執行許多的動態頁面(如:jsp、PHP、APS.NET等)。然而由於HTTP協議自身的特點,使用者每執行一個動態頁面,都需要和Web伺服器重新建立連線。
又由於WEB程式無狀態記憶的特點,此次連線無法得到上次連線的狀態。這樣,使用者在一個動態頁面中對一個變數進行了賦值操作,而在另外一個動態頁面中卻無法得到這個變數的值。例如,使用者在負責登入的動態頁面中設定了string username = "wind",卻無法在另一個動態頁面中通過呼叫 username 來獲得“wind”這個值。也就是說,在程式中無法設定全域性變數。也就是說: 每個動態指令碼中所定義的變數都是隻在這個指令碼內有效的區域性變數。
Session解決方案,就是要提供在動態指令碼中定義全域性變數的方法,使得這個全域性變數在同一個Session中對於所有的動態頁面都有效。上面我們提到了,Session不是一個簡單的時間概念,一個Session中還包括了特定的使用者和伺服器。因此更詳細地講,在一個Session定義的全域性變數的作用範圍,是指這個Session所對應的使用者所訪問的所有動態指令碼。
又因為HTTP協議是一種無狀態連結方式,也就是說服務端與客戶端不是連結在一起的。HTTP是一個客戶端和伺服器端請求和應答的標準(TCP)。客戶端是終端使用者,伺服器端是網站。通過使用Web瀏覽器、網路爬蟲或者其它的工具,客戶端發起一個到伺服器上指定埠(預設埠為80)的HTTP請求。(我們稱這個客戶端)叫使用者代理(user agent)。應答的伺服器上儲存著(一些)資源,比如HTML檔案和影象。(我們稱)這個應答伺服器為源伺服器(origin server)。
在使用者代理和源伺服器中間可能存在多箇中間層,比如代理,閘道器,或者隧道(tunnels)。儘管TCP/IP協議是網際網路上最流行的應用,HTTP協議並沒有規定必須使用它和(基於)它支援的層。 事實上,HTTP可以在任何其他網際網路協議上,或者在其他網路上實現。HTTP只假定(其下層協議提供)可靠的傳輸,任何能夠提供這種保證的協議都可以被其使用。
下面是用PHP實現的HTTP中的POST請求程式碼:<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --> /** * Post 方式請求網頁資料 * * @param string $url 網頁地址 * @prarm string $host 主機 * @param string $session 會話值 * @prarm string $type 型別(POST、GET) * @prarm string $port 埠 * @prarm string $data 資料 */ function getPageConent( $url,$host,$session="",$type="POST",$port="",$data="") { if( empty($port) ) $port=80; /* 請求資料 */ $post_data=$data; $lenght=strlen($post_data); $headers="{$type} {$url} HTTP/1.1\r\n"; $headers.="Accept: * /*\r\n"; $headers.="Content-Type: application/x-www-form-urlencoded\r\n"; $headers.="User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB6; CIBA; .NET CLR 4.0.20506)\r\n"; if($session!="" ) $headers.="Cookie:JSESSIONID={$session}\r\n"; $headers.="Host: {$host}:{$port}\r\n"; $headers.="Content-Length: {$lenght}\r\n"; $headers.="Connection: Close\r\n\r\n"; $headers.=$post_data; if( $fp=fsockopen( $host,$port,$errno,$errstr,100) ) { fwrite($fp,$headers); $header=fread($fp,1024); $content=fread($fp,1024); $content.=fread($fp,1024); $content.=fread($fp,1024); $content.=fread($fp,1024); fclose($fp); } if( $data!="" ) { echo$headers; echo"<hr />"; echo$header; echo"<hr />"; echo$content; echo"<hr />"; exit; } else { return$content; } }
下面是獲取網頁程式碼的程式
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --> /** * 獲取URL地址內容 * * @param string $url 地址 * * @return mixed */ function getUrlContent($url) { $url_parsed=parse_url($url); $host=$url_parsed['host']; $port=$url_parsed['port']; /* Port */ if ( $port==0 ) { $port=80; } /* Path */ $path=$url_parsed['path']; if (empty($path)) { $path="/"; } /* query */ if ( $url_parsed['query'] !="" ) { $path.="?".$url_parsed['query']; } /* Open Page Content */ $out="GET {$path} HTTP/1.0\r\nHost: {$host}\r\n\r\n"; if ($fp= @fsockopen( $host,$port,$errno,$errstr,30 )) { fwrite($fp,$out); $header=fread($fp,1024); fclose($fp); return$header; } else { returnfalse; } }下面是實現POST返回值編碼的程式碼
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --> /** * HTTP 編碼定義 */ if (!function_exists('http-chunked-decode')) { function http_chunked_decode($chunk) { $pos=0; $len=strlen($chunk); $dechunk=null; while(($pos<$len) && ($chunkLenHex=substr($chunk,$pos, ($newlineAt=strpos($chunk,"\n",$pos+1))-$pos))) { if (!is_hex($chunkLenHex)) { trigger_error('Value is not properly chunk encoded',E_USER_WARNING); return$chunk; } $pos=$newlineAt+1; $chunkLen=hexdec(rtrim($chunkLenHex,"\r\n")); $dechunk.=substr($chunk,$pos,$chunkLen); $pos=strpos($chunk,"\n",$pos+$chunkLen) +1; } return$dechunk; } } /** * 判斷一個字串可以代表十六進位制的一個電話號碼 * * @param string $hex * @return boolean true if the string is a hex, otherwise false */ function is_hex($hex) { /* 正則表示式是思想 */ $hex=strtolower(trim(ltrim($hex,"0"))); if (empty($hex)) { $hex=0; }; $dec=hexdec($hex); return ($hex==dechex($dec)); }將驗證碼圖片儲存在本地
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --> /** * 儲存圖片 */ function SaveImgage($content,$dir="img.png") { $content= http_chunked_decode($content); $con=fopen($dir,"w"); fwrite($con,$content); fclose($con); return$dir; }下面是具體的實現程式碼
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --> /* 操作PHP程式碼 */ if( $_POST['Action'] =='ok' ) { $txtpPhone=$_POST['txtpPhone']; $txtMoney=$_POST['txtMoney']; $txtType=$_POST['txtType']; /* post data */ $AGENTS_LOGIN_TYPE="AG2"; $AG2_agentNumber="*************"; $AG2_agentPassword="*********"; $logon_valid=$_POST['txtcode']; $SessionId=$_POST['SessionId']; $LOGIN=""; $postData="LOGINS=LOGIN_IN&AGENTS_LOGIN_TYPE={$AGENTS_LOGIN_TYPE}&AG2_agentNumber={$AG2_agentNumber}&AG2_agentPassword={$AG2_agentPassword}&logon_valid={$logon_valid}&JSESSIONID={$SessionId}"; $img= getPageConent("/agent/login.jsp","www.gz.ct10000.com",$SessionId,"POST","80",$postData); echo$img;exit; } else { $str= getUrlContent("http://www.gz.ct10000.com/agent/index.jsp"); $preg='/JSESSIONID=(.*);/isU'; preg_match_all($preg,$str,$match); $SessionId=$match[1][0]; $coding= getPageConent("/public/image.jsp","www.gz.ct10000.com",$SessionId); $img= SaveImgage($coding); } ?> <!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>使用者交話費</title> </head> <body> <form aaction="index.php" method="post" enctype="application/x-www-form-urlencoded" name="form1" id="form1"> <input type="hidden" name="SessionId" id="SessionId" value="<?=$SessionId?>"/><input type="hidden" name="Action" id="Action" value="ok"/> <span id="Label1">輸入驗證</span><input name="txtcode" type='text' id="txtcode"/><img src="img.png" alt="aa"/><br> <span id="Label1">電話號碼</span><input name="txtpPhone" type="text" id="txtpPhone"/><br /> <span id="Label3">充值金額</span><input name="txtMoney" type="text" id="txtMoney"/><br /> <span id="Label2">電話型別</span><input name="txtType" type="text" id="txtType"/><br /> <input type="submit" name="Button1" value="提交" id="Button1"/> </form> </body> </html>