php 如何使用 SOAP 进行身份验证?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2737685/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to do authentication using SOAP?
提问by Yash Desai
How do I authenticate users with SOAP?
如何使用 SOAP 验证用户?
Will I have to require the user to send his username and password with every SOAP request and I authenticate him against the database?
我是否必须要求用户在每个 SOAP 请求中发送他的用户名和密码,然后我根据数据库对他进行身份验证?
Doesn't that seem to cause unnecessary queries?
这似乎不会引起不必要的查询吗?
回答by Chris K
An easier way would be to authenticate on the first query, build a session record on the server side containing the remote IP address and a token that you give to the client as an authToken. Then have the client pass this authToken in future queries. This authToken has to match the internal session data you keep about the client, but would allow you to avoid having to make round-trips to the database just to do authentication.
一种更简单的方法是在第一次查询时进行身份验证,在服务器端建立一个会话记录,其中包含远程 IP 地址和您作为 authToken 提供给客户端的令牌。然后让客户端在以后的查询中传递这个 authToken。此 authToken 必须与您保留的有关客户端的内部会话数据相匹配,但允许您避免为了进行身份验证而必须往返数据库。
That said, @Marcus Adams has a good point below with regard to stateless-ness. There are people out there pushing all sorts of SOAP security models. WS-Securityis the current state of the art, here. They all work by putting authentication information in the SOAP header - after all, that's why a SOAP message contains both a header and a bodypart.
也就是说,@Marcus Adams 在下面关于无状态性有一个很好的观点。有人在推动各种SOAP 安全模型。 WS-Security是当前最先进的技术,在这里。它们都通过将身份验证信息放入 SOAP 标头中来工作 - 毕竟,这就是 SOAP 消息包含标头和正文部分的原因。
回答by EricP
Here's a simple example of how I use an API validation in the header:
这是我如何在标头中使用 API 验证的一个简单示例:
file portfolio-lookup-client.php
文件组合查找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>';
}
?>
file portfolio-lookup-server.php
文件组合查找服务器.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();
?>
file portfolio-lookup.wsdl
文件组合查找.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>
回答by Marcus Adams
Having the user send the username and password with each request is the way that I've seen most SOAP interfaces implemented. Actually, I've not seen any other implementation other than the API keyidea, which is just trading a Username and Password for some other token.
让用户随每个请求发送用户名和密码是我见过的大多数 SOAP 接口实现的方式。实际上,除了API 密钥思想之外,我还没有看到任何其他实现,这只是用用户名和密码换取其他令牌。
SOAP interfaces should be stateless, like HTTP, so this seems like a normal consequence.
SOAP 接口应该是无状态的,就像 HTTP 一样,所以这似乎是一个正常的结果。
回答by this. __curious_geek
Define a custom SOAP header and exchange authentication credentials in the header. Read values from header and authenticate.
定义自定义 SOAP 标头并在标头中交换身份验证凭据。从标头中读取值并进行身份验证。

