SOAPでユーザーを認証するにはどうすればよいですか?
SOAPリクエストごとにユーザーにユーザー名とパスワードを送信するように要求し、データベースに対してユーザーを認証する必要がありますか?
それは不必要なクエリを引き起こしているように見えませんか?
より簡単な方法は、最初のクエリで認証し、リモートIPアドレスとauthTokenとしてクライアントに提供するトークンを含むセッションレコードをサーバー側で構築することです。次に、クライアントにこのauthTokenを将来のクエリで渡してもらいます。このauthTokenは、クライアントに関して保持する内部セッションデータと一致する必要がありますが、認証を行うためだけにデータベースへのラウンドトリップを行う必要がなくなります。
とは言うものの、@ Marcus Adamsは、ステートレス性に関して以下の良い点を持っています。あらゆる種類の SOAPセキュリティモデル を推進している人々がいます。 WS-Security は、現在の最先端技術です。これらはすべて、認証情報をSOAPヘッダーに入れることで機能します。結局のところ、SOAPメッセージにはヘッダーと本文の両方が含まれているのです。
ヘッダーでAPI検証を使用する方法の簡単な例を次に示します。
ファイルportfolio-lookup-client.php
<?php
ini_set("soap.wsdl_cache_enabled", "0"); // disabling WSDL cache
class portfolioLookupAuth
{
public $apiKey;
public function __construct($key)
{
$this->apiKey = $key;
}
}
$apiKey = "123456";
$url = 'http://mysite.com/php5soap/portfolio-lookup.wsdl';
$client = new SoapClient($url, array("trace" => 1, "exception" => 0));
// Create the header
$auth = new portfolioLookupAuth($apiKey);
// SoapHeader::__construct ( string $namespace , string $name [, mixed $data [, bool $mustunderstand [, string $actor ]]] )
$header = new SoapHeader($url, "APIValidate", $auth, false);
try {
$result = $client->__soapCall("getPortfolioByName", array("portfolioName" => "WQAM"), NULL, $header);
print_r($result);
print "<pre>\n"; print "Request :\n".htmlspecialchars($client->__getLastRequest()) ."\n";
print "Response:\n".htmlspecialchars($client->__getLastResponse())."\n"; print "</pre>";
} catch (SoapFault $exception) {
echo 'Exception Thrown: '.$exception->faultstring.'<br><br>';
}
?>
ファイルportfolio-lookup-server.php
<?php
ini_set("soap.wsdl_cache_enabled", "0"); // disabling WSDL cache
class PortfolioLookupService {
private $apiKey = '123456';
private $portfolios = array(
'WPOW' => 'Power 96 party station.',
'WQAM' => 'Sports radio site.',
'WJBR' => 'Cool sites for bands.',
'WKIS' => 'Kiss Country 2',
);
public function APIValidate($auth){
if($auth->apiKey != $this->apiKey){
throw new SoapFault("Server", "Incorrect key");
}
}
function getPortfolioByName($portfolioName) {
//print_r($portfolioName); exit();
if (isset($this->portfolios[$portfolioName])) {
return $this->portfolios[$portfolioName];
} else {
return 'Portfolio name "'.$portfolioName.'" not found.';
//throw new SoapFault('code', 'string', 'actor', 'detail', 'name', 'header');
throw new SoapFault("Server","Unknown Name '$portfolioName'.");
}
}
function getPortfoliosAll() {
return $this->portfolios;
}
}
$server = new SoapServer("portfolio-lookup.wsdl");
$server->setClass("PortfolioLookupService");
$server->handle();
?>
ファイルportfolio-lookup.wsdl
<?xml version ='1.0' encoding ='UTF-8' ?>
<definitions name='PortfolioLookup'
targetNamespace='http://example.org/PortfolioLookup'
xmlns:tns='PortfolioLookup'
xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'
xmlns:soapenc='http://schemas.xmlsoap.org/soap/encoding/'
xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/'
xmlns='http://schemas.xmlsoap.org/wsdl/'>
<message name='getPortfolioByNameRequest'>
<part name='portfolioName' type='xsd:string'/>
</message>
<message name='getPortfolioByNameResponse'>
<part name='Result' type='xsd:string'/>
</message>
<message name='getPortfoliosAllRequest'>
<part name='portfolioName' type='xsd:string'/>
</message>
<message name='getPortfoliosAllResponse'>
<part name='Result' type='xsd:array'/>
</message>
<message name='APIValidateRequest'>
<part name='apiKey' type='xsd:string'/>
</message>
<message name='APIValidateResponse'>
<part name='testReturn' type='xsd:string'/>
</message>
<portType name='PortfolioLookupPortType'>
<operation name='getPortfolioByName'>
<input message='tns:getPortfolioByNameRequest'/>
<output message='tns:getPortfolioByNameResponse'/>
</operation>
<operation name='getPortfoliosAll'>
<input message='tns:getPortfoliosAllRequest'/>
<output message='tns:getPortfoliosAllResponse'/>
</operation>
<operation name='APIValidate'>
<input message='tns:APIValidateRequest'/>
<output message='tns:APIValidateResponse'/>
</operation>
</portType>
<binding name='PortfolioLookupBinding' type='tns:PortfolioLookupPortType'>
<soap:binding style='rpc'
transport='http://schemas.xmlsoap.org/soap/http'/>
<operation name='getPortfolioByName'>
<soap:operation soapAction='urn:PortfolioLookup#getPortfolioByName'/>
<input>
<soap:body use='encoded' namespace='urn:PortfolioLookup'
encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</input>
<output>
<soap:body use='encoded' namespace='urn:PortfolioLookup'
encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</output>
</operation>
<operation name='getPortfoliosAll'>
<soap:operation soapAction='urn:PortfolioLookup#getPortfoliosAll'/>
<input>
<soap:body use='encoded' namespace='urn:PortfolioLookup'
encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</input>
<output>
<soap:body use='encoded' namespace='urn:PortfolioLookup'
encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</output>
</operation>
</binding>
<service name='PortfolioLookupService'>
<port name='PortfolioLookupPort' binding='PortfolioLookupBinding'>
<soap:address location='http://mysite.com/php5soap/portfolio-lookup-server.php'/>
</port>
</service>
</definitions>
ユーザーに各リクエストでユーザー名とパスワードを送信させることは、私がほとんどのSOAPインターフェースが実装されているのを見た方法です。実際、私はAPIキーアイデア。ユーザー名とパスワードを他のトークンと交換しているだけです。
SOAPインターフェースはHTTPのようにステートレスである必要があるため、これは通常の結果のように思われます。
カスタムSOAPヘッダーを定義し、ヘッダーで認証資格情報を交換します。ヘッダーから値を読み取り、認証します。