简体   繁体   English

如何使用SOAP进行身份验证?

[英]How to do authentication using SOAP?

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? 这似乎不会导致不必要的查询?

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. 更简单的方法是在第一个查询上进行身份验证,在服务器端构建包含远程IP地址的会话记录,以及作为authToken提供给客户端的令牌。 Then have the client pass this authToken in future queries. 然后让客户端在将来的查询中传递此authToken。 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. 此authToken必须匹配您保留的有关客户端的内部会话数据,但允许您避免为了进行身份验证而必须往返数据库。

That said, @Marcus Adams has a good point below with regard to stateless-ness. 也就是说,@Marcus Adams在无国籍方面有一个很好的观点。 There are people out there pushing all sorts of SOAP security models . 有人推动各种SOAP安全模型 WS-Security is the current state of the art, here. WS-Security是目前最先进的技术。 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. 它们都通过将身份验证信息放在SOAP头中来工作 - 毕竟,这就是SOAP消息同时包含头部和bodypart的原因。

Here's a simple example of how I use an API validation in the header: 以下是我在标头中使用API​​验证的简单示例:

file portfolio-lookup-client.php file 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>';  

  }

?>

file portfolio-lookup-server.php file 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();

?>

file portfolio-lookup.wsdl file 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>

Having the user send the username and password with each request is the way that I've seen most SOAP interfaces implemented. 让用户使用每个请求发送用户名和密码是我看到的大多数SOAP接口实现的方式。 Actually, I've not seen any other implementation other than the API key idea, which is just trading a Username and Password for some other token. 实际上,除了API密钥的想法之外,我还没有看到任何其他实现,这只是为其他一些令牌交换用户名和密码。

SOAP interfaces should be stateless, like HTTP, so this seems like a normal consequence. SOAP接口应该是无状态的,比如HTTP,所以这似乎是正常的结果。

Define a custom SOAP header and exchange authentication credentials in the header. 定义自定义SOAP标头并在标头中交换身份验证凭据。 Read values from header and authenticate. 从标头读取值并进行身份验证。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM