Skip to content

Commit d8f4697

Browse files
committed
issue #19 - provide a way to set TimeStamp attribute
1 parent 9538c92 commit d8f4697

File tree

8 files changed

+92
-24
lines changed

8 files changed

+92
-24
lines changed

.docker/Dockerfile

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
FROM splitbrain/phpfarm:jessie
1+
FROM php:7.4-apache
22

3-
RUN apt-get update && apt-get install -y git zip
3+
RUN apt-get update \
4+
&& apt-get install -y libxml2-dev git zip \
5+
&& docker-php-ext-install soap
46

57
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
68
COPY . /var/www/

.github/workflows/sonarcloud.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ jobs:
1111
sonarcloud:
1212
name: SonarCloud
1313
runs-on: ubuntu-latest
14+
permissions:
15+
pull-requests: write
1416
steps:
1517
- uses: actions/checkout@v2
1618
with:
@@ -29,6 +31,7 @@ jobs:
2931
run: vendor/bin/phpunit --coverage-clover coverage.xml --log-junit report.xml
3032

3133
- name: Monitor coverage
34+
if: false
3235
uses: slavcodev/coverage-monitor-action@v1
3336
with:
3437
github_token: ${{ secrets.SECRET_GITHUB_TOKEN }}

README.md

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,22 @@ The `WsSecurity::createWsSecuritySoapHeader` parameters are defined in this orde
4444
- **$mustunderstand**: classic option of the [\SoapClient](http://php.net/manual/en/soapclient.soapclient.php) class
4545
- **$actor**: classic option of the [\SoapClient](http://php.net/manual/en/soapclient.soapclient.php) class
4646
- **$usernameId**: the id to attach to the UsernameToken element, optional
47-
- **$addNonce**: _true_ by default, if true, it adds the nonce element to the header, if false it does not add the nonce element to the header
47+
- **$addNonce**: _true_ by default, if true, it adds the nonce element to the header, if false it does not add the nonce element to the header
48+
49+
## Alternative usage ##
50+
Create an instance of the Security class
51+
```php
52+
use WsdlToPhp\WsSecurity\WsSecurity;
53+
54+
$wsSecurity = new WsSecurity('login', 'password', true, /*$addCreated*/ time());
55+
56+
// access its properties to alter them
57+
$wsSecurity->getSecurity()->getTimestamp()->setAttribute('wsu:Id', 'AnyRequestValue');
58+
59+
// Get the SoapHeader
60+
$header = $security->getSoapHeader($returnSoapHeader = true, $mustunderstand = false, $actor = null);
61+
```
62+
4863

4964
## Testing using [Docker](https://www.docker.com/)
5065
Thanks to the [Docker image](https://hub.docker.com/r/splitbrain/phpfarm) of [phpfarm](https://github.com/fpoirotte/phpfarm), tests can be run locally under *any* PHP version using the cli:
@@ -58,9 +73,9 @@ $ docker-compose up -d --build
5873
You then have a container named `ws_security` in which you can run `composer` commands and `php cli` commands such as:
5974
```bash
6075
# install deps in container (using update ensure it does use the composer.lock file if there is any)
61-
$ docker exec -it ws_security php-7.4 /usr/bin/composer update
76+
$ docker exec -it ws_security php /usr/bin/composer update
6277
# run tests in container
63-
$ docker exec -it ws_security php-7.4 -dmemory_limit=-1 vendor/bin/phpunit
78+
$ docker exec -it ws_security php -dmemory_limit=-1 vendor/bin/phpunit
6479
```
6580

6681
## FAQ

sonar-project.properties

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,5 @@ sonar.organization=wsdltophp
33
sonar.php.coverage.reportPaths=coverage.xml
44
sonar.php.tests.reportPath=report.xml
55

6-
# This is the name and version displayed in the SonarCloud UI.
7-
#sonar.projectName=WsSecurity
8-
#sonar.projectVersion=1.0
9-
10-
# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
11-
#sonar.sources=.
12-
13-
# Encoding of the source code. Default is default system encoding
14-
#sonar.sourceEncoding=UTF-8
6+
sonar.sources=src/
7+
sonar.tests=tests/

src/Password.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public function __construct(string $password, string $typeValue = self::TYPE_PAS
2020
{
2121
$this
2222
->setTypeValue($typeValue)
23-
->setTimestampValue($timestampValue ? $timestampValue : time())
23+
->setTimestampValue($timestampValue ?: time())
2424
->setNonceValue((string) mt_rand())
2525
;
2626

src/Timestamp.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ class Timestamp extends Element
1010
{
1111
public const NAME = 'Timestamp';
1212

13-
protected ?Created $created;
13+
protected ?Created $created = null;
1414

15-
protected ?Expires $expires;
15+
protected ?Expires $expires = null;
1616

1717
public function __construct(string $namespace = self::NS_WSU)
1818
{

src/WsSecurity.php

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class WsSecurity
1111
{
1212
protected Security $security;
1313

14-
protected function __construct(
14+
public function __construct(
1515
string $username,
1616
string $password,
1717
bool $passwordDigest = false,
@@ -55,15 +55,21 @@ public static function createWsSecuritySoapHeader(
5555
string $envelopeNamespace = Security::ENV_NAMESPACE
5656
) {
5757
$self = new WsSecurity($username, $password, $passwordDigest, $addCreated, $addExpires, $mustUnderstand, $actor, $usernameId, $addNonce, $envelopeNamespace);
58+
59+
return $self->getSoapHeader($returnSoapHeader, $mustUnderstand, $actor);
60+
}
61+
62+
public function getSoapHeader(bool $returnSoapHeader = true, bool $mustUnderstand = false, ?string $actor = null): object
63+
{
5864
if ($returnSoapHeader) {
5965
if (!empty($actor)) {
60-
return new SoapHeader(Element::NS_WSSE, Security::NAME, new SoapVar($self->getSecurity()->toSend(), XSD_ANYXML), $mustUnderstand, $actor);
66+
return new SoapHeader(Element::NS_WSSE, Security::NAME, new SoapVar($this->getSecurity()->toSend(), XSD_ANYXML), $mustUnderstand, $actor);
6167
}
6268

63-
return new SoapHeader(Element::NS_WSSE, Security::NAME, new SoapVar($self->getSecurity()->toSend(), XSD_ANYXML), $mustUnderstand);
69+
return new SoapHeader(Element::NS_WSSE, Security::NAME, new SoapVar($this->getSecurity()->toSend(), XSD_ANYXML), $mustUnderstand);
6470
}
6571

66-
return new SoapVar($self->getSecurity()->toSend(), XSD_ANYXML);
72+
return new SoapVar($this->getSecurity()->toSend(), XSD_ANYXML);
6773
}
6874

6975
protected function initSecurity(bool $mustUnderstand = false, ?string $actor = null, string $envelopeNamespace = Security::ENV_NAMESPACE): self
@@ -115,12 +121,18 @@ protected function setCreated(int $addCreated): self
115121
protected function setTimestamp(int $addCreated = 0, int $addExpires = 0): self
116122
{
117123
$timestampValue = $this->getPassword()->getTimestampValue();
118-
if ($addCreated && $addExpires && $timestampValue) {
119-
$timestamp = new Timestamp();
124+
if (!$timestampValue || (0 === $addCreated && 0 === $addExpires)) {
125+
return $this;
126+
}
127+
128+
$timestamp = new Timestamp();
129+
if (0 < $addCreated) {
120130
$timestamp->setCreated(new Created($timestampValue));
131+
}
132+
if (0 < $addExpires) {
121133
$timestamp->setExpires(new Expires($timestampValue, $addExpires));
122-
$this->security->setTimestamp($timestamp);
123134
}
135+
$this->security->setTimestamp($timestamp);
124136

125137
return $this;
126138
}

tests/WsSecurityTest.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ public function testCreateWithoutExpiresIn()
4444
<wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2016-03-31T19:17:04Z</wsu:Created>
4545
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">([a-zA-Z0-9=]*)</wsse:Nonce>
4646
</wsse:UsernameToken>
47+
<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
48+
<wsu:Created>2016-03-31T19:17:04Z</wsu:Created>
49+
</wsu:Timestamp>
4750
</wsse:Security>'), $header->data->enc_value);
4851
}
4952

@@ -59,6 +62,9 @@ public function testCreateWithMustUnderstand()
5962
<wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2016-03-31T19:17:04Z</wsu:Created>
6063
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">([a-zA-Z0-9=]*)</wsse:Nonce>
6164
</wsse:UsernameToken>
65+
<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
66+
<wsu:Created>2016-03-31T19:17:04Z</wsu:Created>
67+
</wsu:Timestamp>
6268
</wsse:Security>'), $header->data->enc_value);
6369
}
6470

@@ -74,6 +80,9 @@ public function testCreateWithMustUnderstandAndActor()
7480
<wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2016-03-31T19:17:04Z</wsu:Created>
7581
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">([a-zA-Z0-9=]*)</wsse:Nonce>
7682
</wsse:UsernameToken>
83+
<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
84+
<wsu:Created>2016-03-31T19:17:04Z</wsu:Created>
85+
</wsu:Timestamp>
7786
</wsse:Security>'), $header->data->enc_value);
7887
}
7988

@@ -89,6 +98,9 @@ public function testCreateSoapVar()
8998
<wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2016-03-31T19:17:04Z</wsu:Created>
9099
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">([a-zA-Z0-9=]*)</wsse:Nonce>
91100
</wsse:UsernameToken>
101+
<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
102+
<wsu:Created>2016-03-31T19:17:04Z</wsu:Created>
103+
</wsu:Timestamp>
92104
</wsse:Security>'), $header->enc_value);
93105
}
94106

@@ -104,6 +116,9 @@ public function testCreateWithPasswordDigest()
104116
<wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2016-03-31T19:17:04Z</wsu:Created>
105117
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">([a-zA-Z0-9=]*)</wsse:Nonce>
106118
</wsse:UsernameToken>
119+
<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
120+
<wsu:Created>2016-03-31T19:17:04Z</wsu:Created>
121+
</wsu:Timestamp>
107122
</wsse:Security>'), $header->enc_value);
108123
}
109124

@@ -119,6 +134,9 @@ public function testCreateWithUsernameId()
119134
<wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2016-03-31T19:17:04Z</wsu:Created>
120135
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">([a-zA-Z0-9=]*)</wsse:Nonce>
121136
</wsse:UsernameToken>
137+
<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
138+
<wsu:Created>2016-03-31T19:17:04Z</wsu:Created>
139+
</wsu:Timestamp>
122140
</wsse:Security>'), $header->data->enc_value);
123141
}
124142

@@ -133,6 +151,28 @@ public function testCreateWithoutNonce()
133151
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">bar</wsse:Password>
134152
<wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2016-03-31T19:17:04Z</wsu:Created>
135153
</wsse:UsernameToken>
154+
<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
155+
<wsu:Created>2016-03-31T19:17:04Z</wsu:Created>
156+
</wsu:Timestamp>
157+
</wsse:Security>'), $header->data->enc_value);
158+
}
159+
160+
public function testWithTimestampAttribute()
161+
{
162+
$security = new WsSecurity('foo', 'bar', false, 1459451824, 0, false, null, null, false);
163+
$security->getSecurity()->getTimestamp()->setAttribute('wsu:Id', 'Timestamp-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX');
164+
$header = $security->getSoapHeader();
165+
$this->assertInstanceOf(SoapHeader::class, $header);
166+
$this->assertMatches(self::innerTrim('
167+
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
168+
<wsse:UsernameToken>
169+
<wsse:Username>foo</wsse:Username>
170+
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">bar</wsse:Password>
171+
<wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2016-03-31T19:17:04Z</wsu:Created>
172+
</wsse:UsernameToken>
173+
<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX">
174+
<wsu:Created>2016-03-31T19:17:04Z</wsu:Created>
175+
</wsu:Timestamp>
136176
</wsse:Security>'), $header->data->enc_value);
137177
}
138178

@@ -161,6 +201,9 @@ public function testCreateWithEnvelopeNamespace()
161201
<wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2016-03-31T19:17:04Z</wsu:Created>
162202
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">([a-zA-Z0-9=]*)</wsse:Nonce>
163203
</wsse:UsernameToken>
204+
<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
205+
<wsu:Created>2016-03-31T19:17:04Z</wsu:Created>
206+
</wsu:Timestamp>
164207
</wsse:Security>'), $header->data->enc_value);
165208
}
166209
}

0 commit comments

Comments
 (0)