CircleOfNice / CiRestClientBundle

Mapper for PHP internal curl library
GNU General Public License v3.0
57 stars 20 forks source link

Support WSSE WADL #30

Closed tuanquynh0508 closed 8 years ago

tuanquynh0508 commented 8 years ago

Does CiRestClientBundle support for call rest service is protectetd by sercurity WSSE?

TobiasHauck commented 8 years ago

Hi Nguyễn Như Tuấn Quỳnh, thank you for opening the issue! We believe that handling WSSE security easily is something that could be provided in future, but not in this bundle. This bundle has the goal to send requests, nothing else.

What you can actually do is to build your own rest client by using the original one:

RestClient

namespace YourNameSpace\RestClient;

use Ci\RestClientBundle\Services\RestClient;
use Circle\WsseBundle\WsseGenerator;

class RestClient {

    private $restClient;

    private $wsseGenerator;

    public function __construct(RestClient $restClient, WsseGenerator $wsseGenerator) {
        $this->restClient    = $restClient;
        $this->wsseGenerator = $wsseGenerator;
    }

    public function get($url, array $options = array(), $username, $password) {
        return $this->restClient->get($url, $this->addWsseHeaders($options));
    }

    private function addWsseHeaders(array $defaultOptions, $username, $password) {
        $wsse = $this->wsseGenerator->generate($username, $password);
        $httpHeaders = isEmpty($defaultOptions[CURLOPT_HTTPHEADER]) ? [ $wsse ] : array_merge($defaultOptions[CURLOPT_HTTPHEADER], [ $wsse ]);

        return array_push($defaultOptions, [ CURLOPT_HTTPHEADER => $httpHeaders ]);
    }
}

Wsse Generator

The WsseString has to look like:

Authorization: WSSE profile="UsernameToken"
X-WSSE: UsernameToken Username="admin", PasswordDigest="mTe5J+wM7tcBsI2Qx7bnajQ+0lQ=", Nonce="OWRmNWEwZWZiMTcyMTRkNQ==", Created="2014-12-09T21:29:18+02:00"

So your WsseGenerator should look like:

<?php

namespace Circle\WsseBundle;

class WsseGenerator {

    public function generate($username, $password) {
        $createdAt      = gmdate('Y-m-d\TH:i:s\Z');
        $passwordDigest = $this->generatePasswordDigest($password, $createdAt);

        return "Authorization: WSSE profile=\"UsernameToken\"\nX-WSSE: UsernameToken Username=\"$username\", PasswordDigest=\"$passwordDigest\", Nonce=\"OWRmNWEwZWZiMTcyMTRkNQ==\", Created=\"$createdAt\"";
    }

    private function generatePasswordDigest($password, $createdAt) {
        return base64_encode(pack('H*', sha1(pack('H*', mt_rand()) . pack('a*', $createdAt) . pack('a*', $password))));
    }
}

Finally define the new service in your services.yml

#services.yml
your.restclient:
    class: YourNameSpace\RestClient
    arguments: [ "@ci.restclient", "@circle.wsse.generator" ]

circle.wsse.generator:
    class: Circle\WsseBundle\WsseGenerator

It would be a pleasure for me if you try this out and give me a feedback :-)

tuanquynh0508 commented 8 years ago

Thanks you TobiasHauck very much. Your comment is very helpful for me. Thanks!.