summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitattributes2
-rw-r--r--.gitignore2
-rw-r--r--Acl/Domain/AclCollectionCache.php4
-rw-r--r--Acl/Domain/PermissionGrantingStrategy.php21
-rw-r--r--Acl/Model/AclProviderInterface.php17
-rw-r--r--Acl/Model/SecurityIdentityRetrievalStrategyInterface.php3
-rw-r--r--CHANGELOG.md3
-rw-r--r--Core/Authentication/Token/AbstractToken.php2
-rw-r--r--Core/Authentication/Token/AnonymousToken.php10
-rw-r--r--Core/Authentication/Token/TokenInterface.php4
-rw-r--r--Core/Authentication/Token/UsernamePasswordToken.php18
-rw-r--r--Core/Role/RoleHierarchyInterface.php4
-rw-r--r--Core/Role/RoleInterface.php2
-rw-r--r--Core/Util/ClassUtils.php5
-rw-r--r--Core/Util/SecureRandomInterface.php1
-rw-r--r--Core/Util/StringUtils.php9
-rw-r--r--Http/EntryPoint/BasicAuthenticationEntryPoint.php2
-rw-r--r--Http/EntryPoint/DigestAuthenticationEntryPoint.php2
-rw-r--r--Http/Firewall.php9
-rw-r--r--Http/Firewall/DigestAuthenticationListener.php13
-rw-r--r--Http/RememberMe/AbstractRememberMeServices.php9
-rw-r--r--Http/RememberMe/PersistentTokenBasedRememberMeServices.php8
-rw-r--r--Http/RememberMe/ResponseListener.php9
-rw-r--r--README.md9
-rwxr-xr-xTests/Core/Util/SecureRandomTest.php1
-rw-r--r--Tests/Http/EntryPoint/BasicAuthenticationEntryPointTest.php2
-rw-r--r--Tests/Http/EntryPoint/DigestAuthenticationEntryPointTest.php3
-rw-r--r--Tests/Http/Firewall/DigestDataTest.php181
-rw-r--r--Tests/Http/RememberMe/AbstractRememberMeServicesTest.php16
-rw-r--r--Tests/Http/RememberMe/TokenBasedRememberMeServicesTest.php2
-rw-r--r--Tests/bootstrap.php22
-rw-r--r--phpunit.xml.dist2
32 files changed, 299 insertions, 98 deletions
diff --git a/.gitattributes b/.gitattributes
index e742c9b..8048151 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,2 +1,2 @@
-Tests/ export-ignore
+/Tests export-ignore
phpunit.xml.dist export-ignore
diff --git a/.gitignore b/.gitignore
index d1502b0..44de97a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
vendor/
composer.lock
+phpunit.xml
+
diff --git a/Acl/Domain/AclCollectionCache.php b/Acl/Domain/AclCollectionCache.php
index 88c017c..d3a4b37 100644
--- a/Acl/Domain/AclCollectionCache.php
+++ b/Acl/Domain/AclCollectionCache.php
@@ -44,8 +44,8 @@ class AclCollectionCache
* Batch loads ACLs for an entire collection; thus, it reduces the number
* of required queries considerably.
*
- * @param mixed $collection anything that can be passed to foreach()
- * @param array $tokens an array of TokenInterface implementations
+ * @param mixed $collection anything that can be passed to foreach()
+ * @param TokenInterface[] $tokens an array of TokenInterface implementations
*/
public function cache($collection, array $tokens = array())
{
diff --git a/Acl/Domain/PermissionGrantingStrategy.php b/Acl/Domain/PermissionGrantingStrategy.php
index 3b4e99a..e075861 100644
--- a/Acl/Domain/PermissionGrantingStrategy.php
+++ b/Acl/Domain/PermissionGrantingStrategy.php
@@ -16,6 +16,7 @@ use Symfony\Component\Security\Acl\Model\AclInterface;
use Symfony\Component\Security\Acl\Model\AuditLoggerInterface;
use Symfony\Component\Security\Acl\Model\EntryInterface;
use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface;
+use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface;
/**
* The permission granting strategy to apply to the access control list.
@@ -120,16 +121,15 @@ class PermissionGrantingStrategy implements PermissionGrantingStrategyInterface
* permission/identity combination.
*
* This process is repeated until either a granting ACE is found, or no
- * permission/identity combinations are left. In the latter case, we will
- * call this method on the parent ACL if it exists, and isEntriesInheriting
- * is true. Otherwise, we will either throw an NoAceFoundException, or deny
- * access finally.
+ * permission/identity combinations are left. Finally, we will either throw
+ * an NoAceFoundException, or deny access.
+ *
+ * @param AclInterface $acl
+ * @param EntryInterface[] $aces An array of ACE to check against
+ * @param array $masks An array of permission masks
+ * @param SecurityIdentityInterface[] $sids An array of SecurityIdentityInterface implementations
+ * @param Boolean $administrativeMode True turns off audit logging
*
- * @param AclInterface $acl
- * @param array $aces An array of ACE to check against
- * @param array $masks An array of permission masks
- * @param array $sids An array of SecurityIdentityInterface implementations
- * @param Boolean $administrativeMode True turns off audit logging
* @return Boolean true, or false; either granting, or denying access respectively.
*/
private function hasSufficientPermissions(AclInterface $acl, array $aces, array $masks, array $sids, $administrativeMode)
@@ -188,7 +188,10 @@ class PermissionGrantingStrategy implements PermissionGrantingStrategyInterface
*
* @param integer $requiredMask
* @param EntryInterface $ace
+ *
* @return Boolean
+ *
+ * @throws \RuntimeException if the ACE strategy is not supported
*/
private function isAceApplicable($requiredMask, EntryInterface $ace)
{
diff --git a/Acl/Model/AclProviderInterface.php b/Acl/Model/AclProviderInterface.php
index bdb40b7..4be49bf 100644
--- a/Acl/Model/AclProviderInterface.php
+++ b/Acl/Model/AclProviderInterface.php
@@ -23,6 +23,7 @@ interface AclProviderInterface
*
* @param ObjectIdentityInterface $parentOid
* @param Boolean $directChildrenOnly
+ *
* @return array returns an array of child 'ObjectIdentity's
*/
public function findChildren(ObjectIdentityInterface $parentOid, $directChildrenOnly = false);
@@ -30,20 +31,24 @@ interface AclProviderInterface
/**
* Returns the ACL that belongs to the given object identity
*
- * @throws AclNotFoundException when there is no ACL
- * @param ObjectIdentityInterface $oid
- * @param array $sids
+ * @param ObjectIdentityInterface $oid
+ * @param SecurityIdentityInterface[] $sids
+ *
* @return AclInterface
+ *
+ * @throws AclNotFoundException when there is no ACL
*/
public function findAcl(ObjectIdentityInterface $oid, array $sids = array());
/**
* Returns the ACLs that belong to the given object identities
*
- * @throws AclNotFoundException when we cannot find an ACL for all identities
- * @param array $oids an array of ObjectIdentityInterface implementations
- * @param array $sids an array of SecurityIdentityInterface implementations
+ * @param ObjectIdentityInterface[] $oids an array of ObjectIdentityInterface implementations
+ * @param SecurityIdentityInterface[] $sids an array of SecurityIdentityInterface implementations
+ *
* @return \SplObjectStorage mapping the passed object identities to ACLs
+ *
+ * @throws AclNotFoundException when we cannot find an ACL for all identities
*/
public function findAcls(array $oids, array $sids = array());
}
diff --git a/Acl/Model/SecurityIdentityRetrievalStrategyInterface.php b/Acl/Model/SecurityIdentityRetrievalStrategyInterface.php
index c20f04b..5bb7915 100644
--- a/Acl/Model/SecurityIdentityRetrievalStrategyInterface.php
+++ b/Acl/Model/SecurityIdentityRetrievalStrategyInterface.php
@@ -28,7 +28,8 @@ interface SecurityIdentityRetrievalStrategyInterface
* least specific.
*
* @param TokenInterface $token
- * @return array of SecurityIdentityInterface implementations
+ *
+ * @return SecurityIdentityInterface[] An array of SecurityIdentityInterface implementations
*/
public function getSecurityIdentities(TokenInterface $token);
}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 279c614..1305b28 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,9 @@ CHANGELOG
2.2.0
-----
+ * `Symfony\Component\Security\Http\Firewall` and
+ `Symfony\Component\Security\Http\RememberMe\ResponseListener` now
+ implements EventSubscriberInterface
* added secure random number generator
* added PBKDF2 Password encoder
diff --git a/Core/Authentication/Token/AbstractToken.php b/Core/Authentication/Token/AbstractToken.php
index ed6e8de..68cbb79 100644
--- a/Core/Authentication/Token/AbstractToken.php
+++ b/Core/Authentication/Token/AbstractToken.php
@@ -33,7 +33,7 @@ abstract class AbstractToken implements TokenInterface
/**
* Constructor.
*
- * @param Role[] $roles An array of roles
+ * @param RoleInterface[] $roles An array of roles
*/
public function __construct(array $roles = array())
{
diff --git a/Core/Authentication/Token/AnonymousToken.php b/Core/Authentication/Token/AnonymousToken.php
index ecdd4cc..9b0a084 100644
--- a/Core/Authentication/Token/AnonymousToken.php
+++ b/Core/Authentication/Token/AnonymousToken.php
@@ -24,9 +24,9 @@ class AnonymousToken extends AbstractToken
/**
* Constructor.
*
- * @param string $key The key shared with the authentication provider
- * @param string $user The user
- * @param Role[] $roles An array of roles
+ * @param string $key The key shared with the authentication provider
+ * @param string $user The user
+ * @param RoleInterface[] $roles An array of roles
*/
public function __construct($key, $user, array $roles = array())
{
@@ -66,9 +66,9 @@ class AnonymousToken extends AbstractToken
/**
* {@inheritDoc}
*/
- public function unserialize($str)
+ public function unserialize($serialized)
{
- list($this->key, $parentStr) = unserialize($str);
+ list($this->key, $parentStr) = unserialize($serialized);
parent::unserialize($parentStr);
}
}
diff --git a/Core/Authentication/Token/TokenInterface.php b/Core/Authentication/Token/TokenInterface.php
index dec31d5..11f69da 100644
--- a/Core/Authentication/Token/TokenInterface.php
+++ b/Core/Authentication/Token/TokenInterface.php
@@ -11,6 +11,8 @@
namespace Symfony\Component\Security\Core\Authentication\Token;
+use Symfony\Component\Security\Core\Role\RoleInterface;
+
/**
* TokenInterface is the interface for the user authentication information.
*
@@ -31,7 +33,7 @@ interface TokenInterface extends \Serializable
/**
* Returns the user roles.
*
- * @return Role[] An array of Role instances.
+ * @return RoleInterface[] An array of RoleInterface instances.
*/
public function getRoles();
diff --git a/Core/Authentication/Token/UsernamePasswordToken.php b/Core/Authentication/Token/UsernamePasswordToken.php
index 95eec54..d6e3998 100644
--- a/Core/Authentication/Token/UsernamePasswordToken.php
+++ b/Core/Authentication/Token/UsernamePasswordToken.php
@@ -24,10 +24,10 @@ class UsernamePasswordToken extends AbstractToken
/**
* Constructor.
*
- * @param string $user The username (like a nickname, email address, etc.), or a UserInterface instance or an object implementing a __toString method.
- * @param string $credentials This usually is the password of the user
- * @param string $providerKey The provider key
- * @param array $roles An array of roles
+ * @param string $user The username (like a nickname, email address, etc.), or a UserInterface instance or an object implementing a __toString method.
+ * @param string $credentials This usually is the password of the user
+ * @param string $providerKey The provider key
+ * @param RoleInterface[] $roles An array of roles
*
* @throws \InvalidArgumentException
*/
@@ -78,14 +78,20 @@ class UsernamePasswordToken extends AbstractToken
$this->credentials = null;
}
+ /**
+ * {@inheritdoc}
+ */
public function serialize()
{
return serialize(array($this->credentials, $this->providerKey, parent::serialize()));
}
- public function unserialize($str)
+ /**
+ * {@inheritdoc}
+ */
+ public function unserialize($serialized)
{
- list($this->credentials, $this->providerKey, $parentStr) = unserialize($str);
+ list($this->credentials, $this->providerKey, $parentStr) = unserialize($serialized);
parent::unserialize($parentStr);
}
}
diff --git a/Core/Role/RoleHierarchyInterface.php b/Core/Role/RoleHierarchyInterface.php
index c495a7f..2ea6ca3 100644
--- a/Core/Role/RoleHierarchyInterface.php
+++ b/Core/Role/RoleHierarchyInterface.php
@@ -24,9 +24,9 @@ interface RoleHierarchyInterface
* Reachable roles are the roles directly assigned but also all roles that
* are transitively reachable from them in the role hierarchy.
*
- * @param array $roles An array of directly assigned roles
+ * @param RoleInterface[] $roles An array of directly assigned roles
*
- * @return array An array of all reachable roles
+ * @return RoleInterface[] An array of all reachable roles
*/
public function getReachableRoles(array $roles);
}
diff --git a/Core/Role/RoleInterface.php b/Core/Role/RoleInterface.php
index a3cb266..3d4cbea 100644
--- a/Core/Role/RoleInterface.php
+++ b/Core/Role/RoleInterface.php
@@ -15,7 +15,7 @@ namespace Symfony\Component\Security\Core\Role;
* RoleInterface represents a role granted to a user.
*
* A role must either have a string representation or it needs to be explicitly
- * supported by an at least one AccessDecisionManager.
+ * supported by at least one AccessDecisionManager.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
diff --git a/Core/Util/ClassUtils.php b/Core/Util/ClassUtils.php
index 7b583a3..26bf1a1 100644
--- a/Core/Util/ClassUtils.php
+++ b/Core/Util/ClassUtils.php
@@ -37,6 +37,11 @@ class ClassUtils
const MARKER_LENGTH = 6;
/**
+ * This class should not be instantiated
+ */
+ private function __construct() {}
+
+ /**
* Gets the real class name of a class name that could be a proxy.
*
* @param string|object
diff --git a/Core/Util/SecureRandomInterface.php b/Core/Util/SecureRandomInterface.php
index 64830a9..bb70a7e 100644
--- a/Core/Util/SecureRandomInterface.php
+++ b/Core/Util/SecureRandomInterface.php
@@ -11,7 +11,6 @@
namespace Symfony\Component\Security\Core\Util;
-use Symfony\Component\HttpKernel\Log\LoggerInterface;
/**
* Interface that needs to be implemented by all secure random number generators.
diff --git a/Core/Util/StringUtils.php b/Core/Util/StringUtils.php
index a73b471..d21efd3 100644
--- a/Core/Util/StringUtils.php
+++ b/Core/Util/StringUtils.php
@@ -16,11 +16,12 @@ namespace Symfony\Component\Security\Core\Util;
*
* @author Fabien Potencier <fabien@symfony.com>
*/
-final class StringUtils
+class StringUtils
{
- final private function __construct()
- {
- }
+ /**
+ * This class should not be instantiated
+ */
+ private function __construct() {}
/**
* Compares two strings.
diff --git a/Http/EntryPoint/BasicAuthenticationEntryPoint.php b/Http/EntryPoint/BasicAuthenticationEntryPoint.php
index 6ba3872..44ece5e 100644
--- a/Http/EntryPoint/BasicAuthenticationEntryPoint.php
+++ b/Http/EntryPoint/BasicAuthenticationEntryPoint.php
@@ -34,7 +34,7 @@ class BasicAuthenticationEntryPoint implements AuthenticationEntryPointInterface
{
$response = new Response();
$response->headers->set('WWW-Authenticate', sprintf('Basic realm="%s"', $this->realmName));
- $response->setStatusCode(401, $authException ? $authException->getMessage() : null);
+ $response->setStatusCode(401);
return $response;
}
diff --git a/Http/EntryPoint/DigestAuthenticationEntryPoint.php b/Http/EntryPoint/DigestAuthenticationEntryPoint.php
index ec92419..37fba85 100644
--- a/Http/EntryPoint/DigestAuthenticationEntryPoint.php
+++ b/Http/EntryPoint/DigestAuthenticationEntryPoint.php
@@ -57,7 +57,7 @@ class DigestAuthenticationEntryPoint implements AuthenticationEntryPointInterfac
$response = new Response();
$response->headers->set('WWW-Authenticate', $authenticateHeader);
- $response->setStatusCode(401, $authException ? $authException->getMessage() : null);
+ $response->setStatusCode(401);
return $response;
}
diff --git a/Http/Firewall.php b/Http/Firewall.php
index a590fd9..e083fdb 100644
--- a/Http/Firewall.php
+++ b/Http/Firewall.php
@@ -12,8 +12,10 @@
namespace Symfony\Component\Security\Http;
use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Firewall uses a FirewallMap to register security listeners for the given
@@ -25,7 +27,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
*
* @author Fabien Potencier <fabien@symfony.com>
*/
-class Firewall
+class Firewall implements EventSubscriberInterface
{
private $map;
private $dispatcher;
@@ -68,4 +70,9 @@ class Firewall
}
}
}
+
+ public static function getSubscribedEvents()
+ {
+ return array(KernelEvents::REQUEST => array('onKernelRequest', 8));
+ }
}
diff --git a/Http/Firewall/DigestAuthenticationListener.php b/Http/Firewall/DigestAuthenticationListener.php
index 5c529da..2bc4aa5 100644
--- a/Http/Firewall/DigestAuthenticationListener.php
+++ b/Http/Firewall/DigestAuthenticationListener.php
@@ -141,11 +141,12 @@ class DigestData
public function __construct($header)
{
$this->header = $header;
- $parts = preg_split('/, /', $header);
+ preg_match_all('/(\w+)=("((?:[^"\\\\]|\\\\.)+)"|([^\s,$]+))/', $header, $matches, PREG_SET_ORDER);
$this->elements = array();
- foreach ($parts as $part) {
- list($key, $value) = explode('=', $part);
- $this->elements[$key] = '"' === $value[0] ? substr($value, 1, -1) : $value;
+ foreach ($matches as $match) {
+ if (isset($match[1]) && isset($match[3])) {
+ $this->elements[$match[1]] = isset($match[4]) ? $match[4] : $match[3];
+ }
}
}
@@ -156,7 +157,7 @@ class DigestData
public function getUsername()
{
- return $this->elements['username'];
+ return strtr($this->elements['username'], array("\\\"" => "\"", "\\\\" => "\\"));
}
public function validateAndDecode($entryPointKey, $expectedRealm)
@@ -188,7 +189,7 @@ class DigestData
$this->nonceExpiryTime = $nonceTokens[0];
if (md5($this->nonceExpiryTime.':'.$entryPointKey) !== $nonceTokens[1]) {
- new BadCredentialsException(sprintf('Nonce token compromised "%s".', $nonceAsPlainText));
+ throw new BadCredentialsException(sprintf('Nonce token compromised "%s".', $nonceAsPlainText));
}
}
diff --git a/Http/RememberMe/AbstractRememberMeServices.php b/Http/RememberMe/AbstractRememberMeServices.php
index 4f7c5b9..1d6a109 100644
--- a/Http/RememberMe/AbstractRememberMeServices.php
+++ b/Http/RememberMe/AbstractRememberMeServices.php
@@ -172,6 +172,9 @@ abstract class AbstractRememberMeServices implements RememberMeServicesInterface
*/
final public function loginSuccess(Request $request, Response $response, TokenInterface $token)
{
+ // Make sure any old remember-me cookies are cancelled
+ $this->cancelCookie($request);
+
if (!$token->getUser() instanceof UserInterface) {
if (null !== $this->logger) {
$this->logger->debug('Remember-me ignores token since it does not contain a UserInterface implementation.');
@@ -192,6 +195,12 @@ abstract class AbstractRememberMeServices implements RememberMeServicesInterface
$this->logger->debug('Remember-me was requested; setting cookie.');
}
+ // Remove attribute from request that sets a NULL cookie.
+ // It was set by $this->cancelCookie()
+ // (cancelCookie does other things too for some RememberMeServices
+ // so we should still call it at the start of this method)
+ $request->attributes->remove(self::COOKIE_ATTR_NAME);
+
$this->onLoginSuccess($request, $response, $token);
}
diff --git a/Http/RememberMe/PersistentTokenBasedRememberMeServices.php b/Http/RememberMe/PersistentTokenBasedRememberMeServices.php
index dbb6429..9f4013d 100644
--- a/Http/RememberMe/PersistentTokenBasedRememberMeServices.php
+++ b/Http/RememberMe/PersistentTokenBasedRememberMeServices.php
@@ -63,10 +63,12 @@ class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices
/**
* {@inheritDoc}
*/
- public function logout(Request $request, Response $response, TokenInterface $token)
+ protected function cancelCookie(Request $request)
{
- parent::logout($request, $response, $token);
+ // Delete cookie on the client
+ parent::cancelCookie($request);
+ // Delete cookie from the tokenProvider
if (null !== ($cookie = $request->cookies->get($this->options['name']))
&& count($parts = $this->decodeCookie($cookie)) === 2
) {
@@ -88,8 +90,6 @@ class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices
$persistentToken = $this->tokenProvider->loadTokenBySeries($series);
if ($persistentToken->getTokenValue() !== $tokenValue) {
- $this->tokenProvider->deleteTokenBySeries($series);
-
throw new CookieTheftException('This token was already used. The account is possibly compromised.');
}
diff --git a/Http/RememberMe/ResponseListener.php b/Http/RememberMe/ResponseListener.php
index 6cbdcb3..03c71c7 100644
--- a/Http/RememberMe/ResponseListener.php
+++ b/Http/RememberMe/ResponseListener.php
@@ -12,13 +12,15 @@
namespace Symfony\Component\Security\Http\RememberMe;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
+use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Adds remember-me cookies to the Response.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
-class ResponseListener
+class ResponseListener implements EventSubscriberInterface
{
public function onKernelResponse(FilterResponseEvent $event)
{
@@ -29,4 +31,9 @@ class ResponseListener
$response->headers->setCookie($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME));
}
}
+
+ public static function getSubscribedEvents()
+ {
+ return array(KernelEvents::RESPONSE => 'onKernelResponse');
+ }
}
diff --git a/README.md b/README.md
index 7ae97b1..057f844 100644
--- a/README.md
+++ b/README.md
@@ -18,9 +18,6 @@ Resources
You can run the unit tests with the following command:
- phpunit
-
-If you also want to run the unit tests that depend on other Symfony
-Components, install dev dependencies before running PHPUnit:
-
- php composer.phar install --dev
+ $ cd path/to/Symfony/Component/Security/
+ $ composer.phar install --dev
+ $ phpunit
diff --git a/Tests/Core/Util/SecureRandomTest.php b/Tests/Core/Util/SecureRandomTest.php
index 230a26a..c7ed016 100755
--- a/Tests/Core/Util/SecureRandomTest.php
+++ b/Tests/Core/Util/SecureRandomTest.php
@@ -11,7 +11,6 @@
namespace Symfony\Component\Security\Tests\Core\Util;
-use Symfony\Component\Security\Core\Util\NullSeedProvider;
use Symfony\Component\Security\Core\Util\SecureRandom;
class SecureRandomTest extends \PHPUnit_Framework_TestCase
diff --git a/Tests/Http/EntryPoint/BasicAuthenticationEntryPointTest.php b/Tests/Http/EntryPoint/BasicAuthenticationEntryPointTest.php
index b442309..b9e289d 100644
--- a/Tests/Http/EntryPoint/BasicAuthenticationEntryPointTest.php
+++ b/Tests/Http/EntryPoint/BasicAuthenticationEntryPointTest.php
@@ -34,7 +34,6 @@ class BasicAuthenticationEntryPointTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('Basic realm="TheRealmName"', $response->headers->get('WWW-Authenticate'));
$this->assertEquals(401, $response->getStatusCode());
- $this->assertAttributeEquals('The exception message', 'statusText', $response);
}
public function testStartWithoutAuthException()
@@ -47,6 +46,5 @@ class BasicAuthenticationEntryPointTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('Basic realm="TheRealmName"', $response->headers->get('WWW-Authenticate'));
$this->assertEquals(401, $response->getStatusCode());
- $this->assertAttributeEquals('Unauthorized', 'statusText', $response);
}
}
diff --git a/Tests/Http/EntryPoint/DigestAuthenticationEntryPointTest.php b/Tests/Http/EntryPoint/DigestAuthenticationEntryPointTest.php
index ae0e3cc..8dfd618 100644
--- a/Tests/Http/EntryPoint/DigestAuthenticationEntryPointTest.php
+++ b/Tests/Http/EntryPoint/DigestAuthenticationEntryPointTest.php
@@ -34,7 +34,6 @@ class DigestAuthenticationEntryPointTest extends \PHPUnit_Framework_TestCase
$response = $entryPoint->start($request, $authenticationException);
$this->assertEquals(401, $response->getStatusCode());
- $this->assertAttributeEquals('TheAuthenticationExceptionMessage', 'statusText', $response);
$this->assertRegExp('/^Digest realm="TheRealmName", qop="auth", nonce="[a-zA-Z0-9\/+]+={0,2}"$/', $response->headers->get('WWW-Authenticate'));
}
@@ -46,7 +45,6 @@ class DigestAuthenticationEntryPointTest extends \PHPUnit_Framework_TestCase
$response = $entryPoint->start($request);
$this->assertEquals(401, $response->getStatusCode());
- $this->assertAttributeEquals('Unauthorized', 'statusText', $response);
$this->assertRegExp('/^Digest realm="TheRealmName", qop="auth", nonce="[a-zA-Z0-9\/+]+={0,2}"$/', $response->headers->get('WWW-Authenticate'));
}
@@ -60,7 +58,6 @@ class DigestAuthenticationEntryPointTest extends \PHPUnit_Framework_TestCase
$response = $entryPoint->start($request, $nonceExpiredException);
$this->assertEquals(401, $response->getStatusCode());
- $this->assertAttributeEquals('TheNonceExpiredExceptionMessage', 'statusText', $response);
$this->assertRegExp('/^Digest realm="TheRealmName", qop="auth", nonce="[a-zA-Z0-9\/+]+={0,2}", stale="true"$/', $response->headers->get('WWW-Authenticate'));
}
}
diff --git a/Tests/Http/Firewall/DigestDataTest.php b/Tests/Http/Firewall/DigestDataTest.php
new file mode 100644
index 0000000..cfb929c
--- /dev/null
+++ b/Tests/Http/Firewall/DigestDataTest.php
@@ -0,0 +1,181 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Security\Tests\Http\Firewall;
+
+use Symfony\Component\Security\Http\Firewall\DigestData;
+
+class DigestDataTest extends \PHPUnit_Framework_TestCase
+{
+ public function testGetResponse()
+ {
+ $digestAuth = new DigestData(
+ 'username="user", realm="Welcome, robot!", ' .
+ 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' .
+ 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
+ 'response="b52938fc9e6d7c01be7702ece9031b42"'
+ );
+
+ $this->assertEquals('b52938fc9e6d7c01be7702ece9031b42', $digestAuth->getResponse());
+ }
+
+ public function testGetUsername()
+ {
+ $digestAuth = new DigestData(
+ 'username="user", realm="Welcome, robot!", ' .
+ 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' .
+ 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
+ 'response="b52938fc9e6d7c01be7702ece9031b42"'
+ );
+
+ $this->assertEquals('user', $digestAuth->getUsername());
+ }
+
+ public function testGetUsernameWithQuote()
+ {
+ $digestAuth = new DigestData(
+ 'username="\"user\"", realm="Welcome, robot!", ' .
+ 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' .
+ 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
+ 'response="b52938fc9e6d7c01be7702ece9031b42"'
+ );
+
+ $this->assertEquals('"user"', $digestAuth->getUsername());
+ }
+
+ public function testGetUsernameWithQuoteAndEscape()
+ {
+ $digestAuth = new DigestData(
+ 'username="\"u\\\\\"ser\"", realm="Welcome, robot!", ' .
+ 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' .
+ 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
+ 'response="b52938fc9e6d7c01be7702ece9031b42"'
+ );
+
+ $this->assertEquals('"u\\"ser"', $digestAuth->getUsername());
+ }
+
+ public function testGetUsernameWithSingleQuote()
+ {
+ $digestAuth = new DigestData(
+ 'username="\"u\'ser\"", realm="Welcome, robot!", ' .
+ 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' .
+ 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
+ 'response="b52938fc9e6d7c01be7702ece9031b42"'
+ );
+
+ $this->assertEquals('"u\'ser"', $digestAuth->getUsername());
+ }
+
+ public function testGetUsernameWithSingleQuoteAndEscape()
+ {
+ $digestAuth = new DigestData(
+ 'username="\"u\\\'ser\"", realm="Welcome, robot!", ' .
+ 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' .
+ 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
+ 'response="b52938fc9e6d7c01be7702ece9031b42"'
+ );
+
+ $this->assertEquals('"u\\\'ser"', $digestAuth->getUsername());
+ }
+
+ public function testGetUsernameWithEscape()
+ {
+ $digestAuth = new DigestData(
+ 'username="\"u\\ser\"", realm="Welcome, robot!", ' .
+ 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' .
+ 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
+ 'response="b52938fc9e6d7c01be7702ece9031b42"'
+ );
+
+ $this->assertEquals('"u\\ser"', $digestAuth->getUsername());
+ }
+
+ public function testValidateAndDecode()
+ {
+ $time = microtime(true);
+ $key = 'ThisIsAKey';
+ $nonce = base64_encode($time . ':' . md5($time . ':' . $key));
+
+ $digestAuth = new DigestData(
+ 'username="user", realm="Welcome, robot!", nonce="' . $nonce . '", ' .
+ 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
+ 'response="b52938fc9e6d7c01be7702ece9031b42"'
+ );
+
+ try {
+ $digestAuth->validateAndDecode($key, 'Welcome, robot!');
+ } catch (\Exception $e) {
+ $this->fail(sprintf('testValidateAndDecode fail with message: %s', $e->getMessage()));
+ }
+ }
+
+ public function testCalculateServerDigest()
+ {
+ $this->calculateServerDigest('user', 'Welcome, robot!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5');
+ }
+
+ public function testCalculateServerDigestWithQuote()
+ {
+ $this->calculateServerDigest('\"user\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5');
+ }
+
+ public function testCalculateServerDigestWithQuoteAndEscape()
+ {
+ $this->calculateServerDigest('\"u\\\\\"ser\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5');
+ }
+
+ public function testCalculateServerDigestEscape()
+ {
+ $this->calculateServerDigest('\"u\\ser\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5');
+ $this->calculateServerDigest('\"u\\ser\\\\\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5');
+ }
+
+ public function testIsNonceExpired()
+ {
+ $time = microtime(true) + 10;
+ $key = 'ThisIsAKey';
+ $nonce = base64_encode($time . ':' . md5($time . ':' . $key));
+
+ $digestAuth = new DigestData(
+ 'username="user", realm="Welcome, robot!", nonce="' . $nonce . '", ' .
+ 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
+ 'response="b52938fc9e6d7c01be7702ece9031b42"'
+ );
+
+ $digestAuth->validateAndDecode($key, 'Welcome, robot!');
+
+ $this->assertFalse($digestAuth->isNonceExpired());
+ }
+
+ protected function setUp()
+ {
+ class_exists('Symfony\Component\Security\Http\Firewall\DigestAuthenticationListener', true);
+ }
+
+ private function calculateServerDigest($username, $realm, $password, $key, $nc, $cnonce, $qop, $method, $uri)
+ {
+ $time = microtime(true);
+ $nonce = base64_encode($time . ':' . md5($time . ':' . $key));
+
+ $response = md5(
+ md5($username . ':' . $realm . ':' . $password) . ':' . $nonce . ':' . $nc . ':' . $cnonce . ':' . $qop . ':' . md5($method . ':' . $uri)
+ );
+
+ $digest = sprintf('username="%s", realm="%s", nonce="%s", uri="%s", cnonce="%s", nc=%s, qop="%s", response="%s"',
+ $username, $realm, $nonce, $uri, $cnonce, $nc, $qop, $response
+ );
+
+ $digestAuth = new DigestData($digest);
+
+ $this->assertEquals($digestAuth->getResponse(), $digestAuth->calculateServerDigest($password, $method));
+ }
+}
diff --git a/Tests/Http/RememberMe/AbstractRememberMeServicesTest.php b/Tests/Http/RememberMe/AbstractRememberMeServicesTest.php
index fc8dffb..8571686 100644
--- a/Tests/Http/RememberMe/AbstractRememberMeServicesTest.php
+++ b/Tests/Http/RememberMe/AbstractRememberMeServicesTest.php
@@ -39,7 +39,7 @@ class AbstractRememberMeServicesTest extends \PHPUnit_Framework_TestCase
public function testAutoLoginReturnsNullWhenNoCookie()
{
- $service = $this->getService(null, array('name' => 'foo'));
+ $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null));
$this->assertNull($service->autoLogin(new Request()));
}
@@ -49,7 +49,7 @@ class AbstractRememberMeServicesTest extends \PHPUnit_Framework_TestCase
*/
public function testAutoLoginThrowsExceptionWhenImplementationDoesNotReturnUserInterface()
{
- $service = $this->getService(null, array('name' => 'foo'));
+ $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null));
$request = new Request;
$request->cookies->set('foo', 'foo');
@@ -64,7 +64,7 @@ class AbstractRememberMeServicesTest extends \PHPUnit_Framework_TestCase
public function testAutoLogin()
{
- $service = $this->getService(null, array('name' => 'foo'));
+ $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null));
$request = new Request();
$request->cookies->set('foo', 'foo');
@@ -112,7 +112,7 @@ class AbstractRememberMeServicesTest extends \PHPUnit_Framework_TestCase
public function testLoginSuccessIsNotProcessedWhenTokenDoesNotContainUserInterfaceImplementation()
{
- $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => true));
+ $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => true, 'path' => null, 'domain' => null));
$request = new Request;
$response = new Response;
$account = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
@@ -135,7 +135,7 @@ class AbstractRememberMeServicesTest extends \PHPUnit_Framework_TestCase
public function testLoginSuccessIsNotProcessedWhenRememberMeIsNotRequested()
{
- $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => false, 'remember_me_parameter' => 'foo'));
+ $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => false, 'remember_me_parameter' => 'foo', 'path' => null, 'domain' => null));
$request = new Request;
$response = new Response;
$account = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
@@ -159,7 +159,7 @@ class AbstractRememberMeServicesTest extends \PHPUnit_Framework_TestCase
public function testLoginSuccessWhenRememberMeAlwaysIsTrue()
{
- $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => true));
+ $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => true, 'path' => null, 'domain' => null));
$request = new Request;
$response = new Response;
$account = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
@@ -184,7 +184,7 @@ class AbstractRememberMeServicesTest extends \PHPUnit_Framework_TestCase
*/
public function testLoginSuccessWhenRememberMeParameterWithPathIsPositive($value)
{
- $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => false, 'remember_me_parameter' => 'foo[bar]'));
+ $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => false, 'remember_me_parameter' => 'foo[bar]', 'path' => null, 'domain' => null));
$request = new Request;
$request->request->set('foo', array('bar' => $value));
@@ -211,7 +211,7 @@ class AbstractRememberMeServicesTest extends \PHPUnit_Framework_TestCase
*/
public function testLoginSuccessWhenRememberMeParameterIsPositive($value)
{
- $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => false, 'remember_me_parameter' => 'foo'));
+ $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => false, 'remember_me_parameter' => 'foo', 'path' => null, 'domain' => null));
$request = new Request;
$request->request->set('foo', $value);
diff --git a/Tests/Http/RememberMe/TokenBasedRememberMeServicesTest.php b/Tests/Http/RememberMe/TokenBasedRememberMeServicesTest.php
index 407db02..6de69f1 100644
--- a/Tests/Http/RememberMe/TokenBasedRememberMeServicesTest.php
+++ b/Tests/Http/RememberMe/TokenBasedRememberMeServicesTest.php
@@ -179,7 +179,7 @@ class TokenBasedRememberMeServicesTest extends \PHPUnit_Framework_TestCase
public function testLoginSuccessIgnoresTokensWhichDoNotContainAnUserInterfaceImplementation()
{
- $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => true));
+ $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => true, 'path' => null, 'domain' => null));
$request = new Request;
$response = new Response;
$token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
diff --git a/Tests/bootstrap.php b/Tests/bootstrap.php
deleted file mode 100644
index 84ae3a6..0000000
--- a/Tests/bootstrap.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-spl_autoload_register(function ($class) {
- if (0 === strpos(ltrim($class, '/'), 'Symfony\Component\Security')) {
- if (file_exists($file = __DIR__.'/../'.substr(str_replace('\\', '/', $class), strlen('Symfony\Component\Security')).'.php')) {
- require_once $file;
- }
- }
-});
-
-if (file_exists($loader = __DIR__.'/../vendor/autoload.php')) {
- require_once $loader;
-}
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 0560cf5..f45a44e 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -9,7 +9,7 @@
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
- bootstrap="Tests/bootstrap.php"
+ bootstrap="vendor/autoload.php"
>
<testsuites>
<testsuite name="Symfony Security Component Test Suite">