在PHP的Soap Extension中, 對於SoapServer來說, 並沒有方法可用得到/處理用戶端發送的SoapHeader資訊.
網上也有很多人認為, 只能通過讀取POST過來的請求XML檔案, 分析, 才能得到用戶端發送過來的SoapHeader.
但, 其實在SoapServer端, 其實是有一種辦法, 可用把SoapHeader當作一個請求來處理, 從而擷取到用戶端提交的SoapHeader資訊.
假設用戶端代碼如下:
<?php<br />/*<br /> * 儲存使用者名稱和密碼的載體<br /> */<br />class SoapUserInfo {<br /> /**<br /> * @var char $name<br /> */<br /> public $name;<br /> /**<br /> * @var char $password<br /> */<br /> public $password;<br /> public function __construct($l, $p) {<br /> $this->Password = $p;<br /> $this->Username = $l;<br /> }<br />}<br />?>
然後用戶端產生SoapHeader
<?php<br /> $soap_header = new SoapHeader("http://www.laruence.com", 'Authorise'<br /> , new SoapUserInfo('laruence', 'password'), false, SOAP_ACTOR_NEXT);<br />?>
也許細心的同學會注意到第4個參數FALSE和第5個參數SOAP_ACTOR_NEXT, 這是什麼呢? 我最後再講.
然後, 建立用戶端, 綁定SoapHeader
<?php<br /> $client = new SoapClient($wsdl);<br /> $client->__setSoapHeaders(array($soap_header));<br /> $client->__soapCall('request', array());<br />?>
現在, 用戶端已經發起了請求, 請求中也包含了SoapHeader, 其中有了我們驗證需要的使用者名稱/密碼資訊.
那麼, 在服務端, 該如何做呢?
<?php<br />$server = new SoapServer('laruence.wsdl');<br />$server->setClass('InterfaceClass');<br />$server->handle();<br />?>
關鍵的地方就在, 服務端接收請求以後, 會執行個體化一個處理類, 然後分析SoapHeader, 接著就會調用InterfaceClass::Authorise這個方法(Authorise是我們要求標頭中的變數名), 所以, 我們就可用在InterfaceClass類中, 定義個Authorise方法, 並在這個方法中對SoapHeader中的資訊做驗證.
然後, 請求體(Soap body)中的方法被調用, 因為不論Authorise方法返回什麼(除非exit), 請求體中的方法一定會被調用, 所以要尋找個變數記錄驗證的結果.
<?php<br />class InterfaceClass {<br /> /**<br /> * @var bool $authorized<br /> */<br /> private $authorized = FALSE;<br /> /*<br /> * Authentication function<br /> *<br /> * @param string username<br /> * @param string password<br /> */<br /> public function Authentication($username, $password) {<br /> $this->authorized = validateUser($username, $password);<br /> }<br /> /*<br /> * Test method<br /> */<br /> public function request(){<br /> if ($this->authorized) {<br /> //驗證成功, 繼續處理.<br /> } else {<br /> //驗證失敗, 拒絕請求.<br /> }<br /> }<br />}<br />?>
當然, 對於網上說的另外一種方法, 通過分析請求的XML檔案, 也可以:
<?php<br />class InterfaceClass {<br /> /**<br /> * @var bool $authorized<br /> */<br /> private $authorized = FALSE;<br /> function __construct() {<br /> $xml = file_get_contents('php://input');<br /> //分析xml, 獲得SoapHeader資料, 驗證<br /> }<br />}<br />?>
Must Understand
這個參數指明了, 是否服務端必須要瞭解SoapHeader, 如果這個參數為真, 而服務端並不能識別響應的Header, 則會引發一個Soap Fault(Header not understood).
SOAP_ACTOR_NEXT
actor指明了SoapHeader要傳遞給誰, 被誰處理.
SOAP_ACTOR_NEXT的意思就是, 下一個接受到這個要求標頭的Service, 在本文的例子中只有一個Server,當然也就沒有關係了.
在SoapServer的建構函式中, 我們可以指明一個Server的Actor, 比如:
<?php<br />$server = new SoapServer($wsdl, array('actor' => 'laruence'));<br />?>
這樣, 我們就可以在Client的SoapHeader中, 通過設定actor是laruence, 來讓指定的Server來獲得我們設定的頭部的資訊.
note :把我偶像 惠新宸(laruence)大哥的東西轉來 ,可以總是 (Header not understood)。還沒有實驗成功,也可能是我的wsdl 寫錯了。
nonwsdl 下還是 成功的
源地址:http://www.laruence.com/2010/03/26/1365.html