-
-
Save Turin86/5569152 to your computer and use it in GitHub Desktop.
| <?php | |
| /** | |
| * This class can add WSSecurity authentication support to SOAP clients | |
| * implemented with the PHP 5 SOAP extension. | |
| * | |
| * It extends the PHP 5 SOAP client support to add the necessary XML tags to | |
| * the SOAP client requests in order to authenticate on behalf of a given | |
| * user with a given password. | |
| * | |
| * This class was tested with Axis, WSS4J servers and CXF. | |
| * | |
| * @author Roger Veciana - http://www.phpclasses.org/browse/author/233806.html | |
| * @author John Kary <[email protected]> | |
| * @author Alberto Martínez - https://gist.github.com/Turin86/5569152 | |
| * @see http://stackoverflow.com/questions/2987907/how-to-implement-ws-security-1-1-in-php5 | |
| */ | |
| class WSSoapClient extends SoapClient | |
| { | |
| private $OASIS = 'http://docs.oasis-open.org/wss/2004/01'; | |
| /** | |
| * WS-Security Username | |
| * @var string | |
| */ | |
| private $username; | |
| /** | |
| * WS-Security Password | |
| * @var string | |
| */ | |
| private $password; | |
| /** | |
| * WS-Security PasswordType | |
| * @var string | |
| */ | |
| private $passwordType; | |
| /** | |
| * Set WS-Security credentials | |
| * | |
| * @param string $username | |
| * @param string $password | |
| * @param string $passwordType | |
| */ | |
| public function __setUsernameToken($username, $password, $passwordType) | |
| { | |
| $this->username = $username; | |
| $this->password = $password; | |
| $this->passwordType = $passwordType; | |
| } | |
| /** | |
| * Overwrites the original method adding the security header. | |
| * As you can see, if you want to add more headers, the method needs to be modified. | |
| */ | |
| public function __call($function_name, $arguments) | |
| { | |
| $this->__setSoapHeaders($this->generateWSSecurityHeader()); | |
| return parent::__call($function_name, $arguments); | |
| } | |
| /** | |
| * Generate password digest. | |
| * | |
| * Using the password directly may work also, but it's not secure to transmit it without encryption. | |
| * And anyway, at least with axis+wss4j, the nonce and timestamp are mandatory anyway. | |
| * | |
| * @return string base64 encoded password digest | |
| */ | |
| private function generatePasswordDigest() | |
| { | |
| $this->nonce = mt_rand(); | |
| $this->timestamp = gmdate('Y-m-d\TH:i:s\Z'); | |
| $packedNonce = pack('H*', $this->nonce); | |
| $packedTimestamp = pack('a*', $this->timestamp); | |
| $packedPassword = pack('a*', $this->password); | |
| $hash = sha1($packedNonce . $packedTimestamp . $packedPassword); | |
| $packedHash = pack('H*', $hash); | |
| return base64_encode($packedHash); | |
| } | |
| /** | |
| * Generates WS-Security headers | |
| * | |
| * @return SoapHeader | |
| */ | |
| private function generateWSSecurityHeader() | |
| { | |
| if ($this->passwordType === 'PasswordDigest') | |
| { | |
| $password = $this->generatePasswordDigest(); | |
| $nonce = sha1($this->nonce); | |
| } | |
| elseif ($this->passwordType === 'PasswordText') | |
| { | |
| $password = $this->password; | |
| $nonce = sha1(mt_rand()); | |
| } | |
| else | |
| { | |
| return ''; | |
| } | |
| $xml = ' | |
| <wsse:Security SOAP-ENV:mustUnderstand="1" xmlns:wsse="' . $this->OASIS . '/oasis-200401-wss-wssecurity-secext-1.0.xsd"> | |
| <wsse:UsernameToken> | |
| <wsse:Username>' . $this->username . '</wsse:Username> | |
| <wsse:Password Type="' . $this->OASIS . '/oasis-200401-wss-username-token-profile-1.0#' . $this->passwordType . '">' . $password . '</wsse:Password> | |
| <wsse:Nonce EncodingType="' . $this->OASIS . '/oasis-200401-wss-soap-message-security-1.0#Base64Binary">' . $nonce . '</wsse:Nonce>'; | |
| if ($this->passwordType === 'PasswordDigest') | |
| { | |
| $xml .= "\n\t" . '<wsu:Created xmlns:wsu="' . $this->OASIS . '/oasis-200401-wss-wssecurity-utility-1.0.xsd">' . $this->timestamp . '</wsu:Created>'; | |
| } | |
| $xml .= ' | |
| </wsse:UsernameToken> | |
| </wsse:Security>'; | |
| return new SoapHeader( | |
| $this->OASIS . '/oasis-200401-wss-wssecurity-secext-1.0.xsd', | |
| 'Security', | |
| new SoapVar($xml, XSD_ANYXML), | |
| true); | |
| } | |
| } |
Sí, le gustaría firmar con un certificado ssl, ¿cómo sería el proceso?
Llame al constructor WSSoapClient (no anula el constructor SoapClient) con los parámetros apropiados.
https://www.php.net/manual/en/soapclient.soapclient.php#120888
You will have an example of consumption and use this in the header that I get from the SOAPUI
`soapenv:Header
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-B89D7F960777898D89160631426090014">
wsse:Username########</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">#####</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">sBRMmGjIObO6tX0KjOScFA==</wsse:Nonce>
wsu:Created2020-11-25T16:24:20.900Z</wsu:Created>
</wsse:UsernameToken>
<wsu:Timestamp wsu:Id="TS-B89D7F960777898D89160631426090013">
wsu:Created2020-11-25T16:24:20.899Z</wsu:Created>
wsu:Expires2020-11-25T16:25:20.899Z</wsu:Expires>
</wsu:Timestamp>
<wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1" wsu:Id="X509-B89D7F960777898D8916063142608618">########CERTIFICA######################/s
</wsse:BinarySecurityToken>
<ds:Signature Id="SIG-B89D7F960777898D89160631426089212" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
ds:SignedInfo<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces PrefixList="soapenv v1" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:CanonicalizationMethod><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#id-B89D7F960777898D89160631426086111">
ds:Transforms<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces PrefixList="v1" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
ds:DigestValueURDCHKG444RS#/SHsbPH+oRVOS53qjc=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
ds:SignatureValueybjaTDbfjaxY8lCePbN43aIlJ4AINQeGomIkHSbCoYxH+JUQxeIhUSwo+3VbYG9BCQAX/U6bgyup
00KSASncniw3qWWSAE9z1d/73zwgAz88ykIuMSxVEC70qc5FoxLXPvQZad15SQjOkyjfDFG83ZTu
YrNLX11bBQfYjhHhfMQFn+####AAAdlJ2fcRpzPBsSo5VzZtKiNrkbV
1hI/##$$$fFSASASq8tK6RJxSgzCZmmcDz
3JZA652vHyyT4Sws/ChtSaY1oOS3v0a6LkQJ1w==
</ds:SignatureValue>
<ds:KeyInfo Id="KI-B89D7F960777898D8916063142608619">
<wsse:SecurityTokenReference wsse11:TokenType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1" wsu:Id="STR-B89D7F960777898D89160631426086110" xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd">
<wsse:Reference URI="#X509-B89D7F960777898D8916063142608618" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1"/>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
</wsse:Security>
</soapenv:Header>`
Sí, le gustaría firmar con un certificado ssl, ¿cómo sería el proceso?
Llame al constructor WSSoapClient (no anula el constructor SoapClient) con los parámetros apropiados.
https://www.php.net/manual/en/soapclient.soapclient.php#120888Tendrás un ejemplo de consumo y lo usarás en el encabezado que obtengo de la SOAPUI
`soapenv: Header
<wsse: Security xmlns: wsse =" http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd "xmlns: wsu =" http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd ">
<wsse: UsernameToken wsu: Id =" UsernameToken-B89D7F960777898D89160631426090014 ">
wsse: Nombre de usuario ######## </ wsse: Nombre de usuario>
<wsse: Tipo de contraseña = " http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile -1.0 # PasswordText "> ##### </ wsse: Password>
<wsse: Nonce EncodingType =" http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap- message-security-1.0 # Base64Binary "> sBRMmGjIObO6tX0KjOScFA == </ wsse: Nonce>
wsu: Created2020-11-25T16: 24: 20.900Z </ wsu: Created>
</ wsse: UsernameToken>
<wsu: Timestamp wsu: Id = "TS-B89D7F960777898D89160631426090013">
wsu: Created2020-11-25T16: 24: 20.899Z </ wsu: Creado>
wsu: Expires2020-11-25T16: 25: 20.899Z </ wsu: Expires>
</ wsu: Timestamp>
<wsse: BinarySecurityToken EncodingType = " http://docs.oasis-open.org/wss /2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary "ValueType =" http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509- token-profile-1.0 # X509PKIPathv1 "wsu: Id =" X509-B89D7F960777898D8916063142608618 "> ######## CERTIFICA ###################### / s
</ wsse: BinarySecurityToken>
<ds:ID de firma = "SIG-B89D7F960777898D89160631426089212" xmlns: ds = "http://www.w3.org/2000/09/xmldsig# ">
ds: SignedInfo <ds: CanonicalizationMethod Algorithm =" http://www.w3.org/2001/10/xml-exc-c14n# ">
<ec: InclusiveNamespaces PrefixList = "soapenv v1" xmlns: ec = " http://www.w3.org/2001/10/xml-exc-c14n#" />
</ ds: CanonicalizationMethod> <ds: SignatureMethod Algorithm = " http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<ds: Reference URI = "# id-B89D7F960777898D89160631426086111">
ds: Transforms <ds: Transform Algorithm = " http: // www.w3.org/2001/10/xml-exc-c14n # ">
<ec: InclusiveNamespaces PrefixList =" v1 "xmlns: ec =" http://www.w3.org/2001/10/xml-exc- c14n # "/>
</ ds:Transformar> </ ds: Transformaciones> <ds: DigestMethod Algorithm = " http://www.w3.org/2000/09/xmldsig#sha1" />
DS: DigestValueURDCHKG444RS # / SHsbPH + oRVOS53qjc = </ ds: DigestValue>
</ ds: Reference>
</ ds: SignedInfo>
ds: SignatureValueybjaTDbfjaxY8lCePbN43aIlJ4AINQeGomIkHSbCoYxH + + JUQxeIhUSwo 3VbYG9BCQAX / U6bgyup
00KSASncniw3qWWSAE9z1d / 73zwgAz88ykIuMSxVEC70qc5FoxLXPvQZad15SQjOkyjfDFG83ZTu
YrNLX11bBQfYjhHhfMQFn + #### AAAdlJ2fcRpzPBsSo5VzZtKiNrkbV
1ALT / ## $ $$ fFSASASq8tK6RJxSgzCZmmcDz
3JZA652vHyyT4Sws / ChtSaY1oOS3v0a6LkQJ1w ==
</ ds: SignatureValue>
<ds: KeyInfo Id = "KI-B89D7F960777898D8916063142608619">
<wsse: SecurityTokenReference wsse11: TokenType =" http://docs.oasis-open.org/wss/2004 /01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1 "wsu: Id ="STR-B89D7F960777898D89160631426086110 "xmlns: wsse11 ="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd ">
<wsse: Reference URI =" # X509-B89D7F960777898D8916063142608618 "ValueType =" http: //docs.oasis- open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1 "/>
</ wsse: SecurityTokenReference>
</ ds: KeyInfo>
</ ds: Signature>
</ wsse: Seguridad></ soapenv: Encabezado> `
you got an example with the certificate too?
Hi anyone knows how to implement ws security with a certificate X509 to a soap request instead? need help . thanks
Hello, can you please help me what should it be called?
I have PHP 8.0.2
Man this saved the day, I tried the original and it wasn't working for my needs but your fork saved me. Thanks.
Hello, can you please help me what should it be called?
I have PHP 8.0.2
Call the WSSoapClient contructor (does not override the SoapClient constructor) with the appropiate parameters.
https://www.php.net/manual/en/soapclient.soapclient.php#120888