diff options
195 files changed, 4401 insertions, 566 deletions
@@ -1,2 +1,4 @@ vendor/ composer.lock +phpunit.xml + diff --git a/Acl/Dbal/AclProvider.php b/Acl/Dbal/AclProvider.php index 8413843..6f47231 100644 --- a/Acl/Dbal/AclProvider.php +++ b/Acl/Dbal/AclProvider.php @@ -258,16 +258,40 @@ SELECTCLAUSE; WHERE ( SELECTCLAUSE; - $where = '(o.object_identifier = %s AND c.class_type = %s)'; - for ($i=0,$c=count($batch); $i<$c; $i++) { + $types = array(); + $count = count($batch); + for ($i = 0; $i < $count; $i++) { + if (!isset($types[$batch[$i]->getType()])) { + $types[$batch[$i]->getType()] = true; + if ($count > 1) { + break; + } + } + } + + if (1 === count($types)) { + $ids = array(); + for ($i = 0; $i < $count; $i++) { + $ids[] = $this->connection->quote($batch[$i]->getIdentifier()); + } + $sql .= sprintf( - $where, - $this->connection->quote($batch[$i]->getIdentifier()), - $this->connection->quote($batch[$i]->getType()) + '(o.object_identifier IN (%s) AND c.class_type = %s)', + implode(',', $ids), + $this->connection->quote($batch[0]->getType()) ); - - if ($i+1 < $c) { - $sql .= ' OR '; + } else { + $where = '(o.object_identifier = %s AND c.class_type = %s)'; + for ($i = 0; $i < $count; $i++) { + $sql .= sprintf( + $where, + $this->connection->quote($batch[$i]->getIdentifier()), + $this->connection->quote($batch[$i]->getType()) + ); + + if ($i+1 < $count) { + $sql .= ' OR '; + } } } @@ -339,7 +363,7 @@ QUERY; * @param ObjectIdentityInterface $oid * @return integer */ - protected final function retrieveObjectIdentityPrimaryKey(ObjectIdentityInterface $oid) + final protected function retrieveObjectIdentityPrimaryKey(ObjectIdentityInterface $oid) { return $this->connection->executeQuery($this->getSelectObjectIdentityIdSql($oid))->fetchColumn(); } @@ -417,6 +441,8 @@ QUERY; * @param array $oidLookup * * @return \SplObjectStorage mapping object identities to ACL instances + * + * @throws AclNotFoundException */ private function lookupObjectIdentities(array $batch, array $sids, array $oidLookup) { diff --git a/Acl/Dbal/MutableAclProvider.php b/Acl/Dbal/MutableAclProvider.php index 0d46f3a..0ac4fa7 100644 --- a/Acl/Dbal/MutableAclProvider.php +++ b/Acl/Dbal/MutableAclProvider.php @@ -17,7 +17,6 @@ use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity; use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity; use Symfony\Component\Security\Acl\Exception\AclAlreadyExistsException; use Symfony\Component\Security\Acl\Exception\ConcurrentModificationException; -use Symfony\Component\Security\Acl\Exception\Exception; use Symfony\Component\Security\Acl\Model\AclCacheInterface; use Symfony\Component\Security\Acl\Model\AclInterface; use Symfony\Component\Security\Acl\Model\EntryInterface; @@ -148,6 +147,8 @@ class MutableAclProvider extends AclProvider implements MutableAclProviderInterf * @param string $propertyName * @param mixed $oldValue * @param mixed $newValue + * + * @throws \InvalidArgumentException */ public function propertyChanged($sender, $propertyName, $oldValue, $newValue) { diff --git a/Acl/Domain/Acl.php b/Acl/Domain/Acl.php index 6d53131..4665c0e 100644 --- a/Acl/Domain/Acl.php +++ b/Acl/Domain/Acl.php @@ -19,7 +19,6 @@ use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface; use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface; use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface; - /** * An ACL implementation. * diff --git a/Acl/Domain/AclCollectionCache.php b/Acl/Domain/AclCollectionCache.php index be082c1..d3a4b37 100644 --- a/Acl/Domain/AclCollectionCache.php +++ b/Acl/Domain/AclCollectionCache.php @@ -29,9 +29,9 @@ class AclCollectionCache /** * Constructor. * - * @param AclProviderInterface $aclProvider - * @param ObjectIdentityRetrievalStrategy $oidRetrievalStrategy - * @param SecurityIdentityRetrievalStrategy $sidRetrievalStrategy + * @param AclProviderInterface $aclProvider + * @param ObjectIdentityRetrievalStrategyInterface $oidRetrievalStrategy + * @param SecurityIdentityRetrievalStrategyInterface $sidRetrievalStrategy */ public function __construct(AclProviderInterface $aclProvider, ObjectIdentityRetrievalStrategyInterface $oidRetrievalStrategy, SecurityIdentityRetrievalStrategyInterface $sidRetrievalStrategy) { @@ -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/DoctrineAclCache.php b/Acl/Domain/DoctrineAclCache.php index 731f98c..bfc5452 100644 --- a/Acl/Domain/DoctrineAclCache.php +++ b/Acl/Domain/DoctrineAclCache.php @@ -36,6 +36,8 @@ class DoctrineAclCache implements AclCacheInterface * @param Cache $cache * @param PermissionGrantingStrategyInterface $permissionGrantingStrategy * @param string $prefix + * + * @throws \InvalidArgumentException */ public function __construct(Cache $cache, PermissionGrantingStrategyInterface $permissionGrantingStrategy, $prefix = self::PREFIX) { diff --git a/Acl/Domain/ObjectIdentity.php b/Acl/Domain/ObjectIdentity.php index e37e82b..d7d5f84 100644 --- a/Acl/Domain/ObjectIdentity.php +++ b/Acl/Domain/ObjectIdentity.php @@ -31,6 +31,8 @@ final class ObjectIdentity implements ObjectIdentityInterface * * @param string $identifier * @param string $type + * + * @throws \InvalidArgumentException */ public function __construct($identifier, $type) { @@ -49,10 +51,10 @@ final class ObjectIdentity implements ObjectIdentityInterface * Constructs an ObjectIdentity for the given domain object * * @param object $domainObject - * @throws \InvalidArgumentException + * @throws InvalidDomainObjectException * @return ObjectIdentity */ - static public function fromDomainObject($domainObject) + public static function fromDomainObject($domainObject) { if (!is_object($domainObject)) { throw new InvalidDomainObjectException('$domainObject must be an object.'); diff --git a/Acl/Domain/PermissionGrantingStrategy.php b/Acl/Domain/PermissionGrantingStrategy.php index c34db2a..d505843 100644 --- a/Acl/Domain/PermissionGrantingStrategy.php +++ b/Acl/Domain/PermissionGrantingStrategy.php @@ -121,17 +121,18 @@ 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. + * + * @throws NoAceFoundException */ private function hasSufficientPermissions(AclInterface $acl, array $aces, array $masks, array $sids, $administrativeMode) { @@ -189,7 +190,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/Domain/UserSecurityIdentity.php b/Acl/Domain/UserSecurityIdentity.php index 040e43b..3166a1a 100644 --- a/Acl/Domain/UserSecurityIdentity.php +++ b/Acl/Domain/UserSecurityIdentity.php @@ -31,6 +31,8 @@ final class UserSecurityIdentity implements SecurityIdentityInterface * * @param string $username the username representation * @param string $class the user's fully qualified class name + * + * @throws \InvalidArgumentException */ public function __construct($username, $class) { @@ -51,7 +53,7 @@ final class UserSecurityIdentity implements SecurityIdentityInterface * @param UserInterface $user * @return UserSecurityIdentity */ - static public function fromAccount(UserInterface $user) + public static function fromAccount(UserInterface $user) { return new self($user->getUsername(), ClassUtils::getRealClass($user)); } @@ -62,7 +64,7 @@ final class UserSecurityIdentity implements SecurityIdentityInterface * @param TokenInterface $token * @return UserSecurityIdentity */ - static public function fromToken(TokenInterface $token) + public static function fromToken(TokenInterface $token) { $user = $token->getUser(); diff --git a/Acl/Model/AclCacheInterface.php b/Acl/Model/AclCacheInterface.php index dd515ce..ea9604e 100644 --- a/Acl/Model/AclCacheInterface.php +++ b/Acl/Model/AclCacheInterface.php @@ -23,7 +23,7 @@ interface AclCacheInterface * * @param string $primaryKey a serialized primary key */ - function evictFromCacheById($primaryKey); + public function evictFromCacheById($primaryKey); /** * Removes an ACL from the cache @@ -32,7 +32,7 @@ interface AclCacheInterface * * @param ObjectIdentityInterface $oid */ - function evictFromCacheByIdentity(ObjectIdentityInterface $oid); + public function evictFromCacheByIdentity(ObjectIdentityInterface $oid); /** * Retrieves an ACL for the given object identity primary key from the cache @@ -40,7 +40,7 @@ interface AclCacheInterface * @param integer $primaryKey * @return AclInterface */ - function getFromCacheById($primaryKey); + public function getFromCacheById($primaryKey); /** * Retrieves an ACL for the given object identity from the cache @@ -48,17 +48,17 @@ interface AclCacheInterface * @param ObjectIdentityInterface $oid * @return AclInterface */ - function getFromCacheByIdentity(ObjectIdentityInterface $oid); + public function getFromCacheByIdentity(ObjectIdentityInterface $oid); /** * Stores a new ACL in the cache * * @param AclInterface $acl */ - function putInCache(AclInterface $acl); + public function putInCache(AclInterface $acl); /** * Removes all ACLs from the cache */ - function clearCache(); + public function clearCache(); } diff --git a/Acl/Model/AclInterface.php b/Acl/Model/AclInterface.php index 9094560..fffe591 100644 --- a/Acl/Model/AclInterface.php +++ b/Acl/Model/AclInterface.php @@ -28,7 +28,7 @@ interface AclInterface extends \Serializable * * @return array */ - function getClassAces(); + public function getClassAces(); /** * Returns all class-field-based ACEs associated with this ACL @@ -36,14 +36,14 @@ interface AclInterface extends \Serializable * @param string $field * @return array */ - function getClassFieldAces($field); + public function getClassFieldAces($field); /** * Returns all object-based ACEs associated with this ACL * * @return array */ - function getObjectAces(); + public function getObjectAces(); /** * Returns all object-field-based ACEs associated with this ACL @@ -51,28 +51,28 @@ interface AclInterface extends \Serializable * @param string $field * @return array */ - function getObjectFieldAces($field); + public function getObjectFieldAces($field); /** * Returns the object identity associated with this ACL * * @return ObjectIdentityInterface */ - function getObjectIdentity(); + public function getObjectIdentity(); /** * Returns the parent ACL, or null if there is none. * * @return AclInterface|null */ - function getParentAcl(); + public function getParentAcl(); /** * Whether this ACL is inheriting ACEs from a parent ACL. * * @return Boolean */ - function isEntriesInheriting(); + public function isEntriesInheriting(); /** * Determines whether field access is granted @@ -83,7 +83,7 @@ interface AclInterface extends \Serializable * @param Boolean $administrativeMode * @return Boolean */ - function isFieldGranted($field, array $masks, array $securityIdentities, $administrativeMode = false); + public function isFieldGranted($field, array $masks, array $securityIdentities, $administrativeMode = false); /** * Determines whether access is granted @@ -94,7 +94,7 @@ interface AclInterface extends \Serializable * @param Boolean $administrativeMode * @return Boolean */ - function isGranted(array $masks, array $securityIdentities, $administrativeMode = false); + public function isGranted(array $masks, array $securityIdentities, $administrativeMode = false); /** * Whether the ACL has loaded ACEs for all of the passed security identities @@ -102,5 +102,5 @@ interface AclInterface extends \Serializable * @param mixed $securityIdentities an implementation of SecurityIdentityInterface, or an array thereof * @return Boolean */ - function isSidLoaded($securityIdentities); + public function isSidLoaded($securityIdentities); } diff --git a/Acl/Model/AclProviderInterface.php b/Acl/Model/AclProviderInterface.php index 2f878e1..4be49bf 100644 --- a/Acl/Model/AclProviderInterface.php +++ b/Acl/Model/AclProviderInterface.php @@ -23,27 +23,32 @@ interface AclProviderInterface * * @param ObjectIdentityInterface $parentOid * @param Boolean $directChildrenOnly + * * @return array returns an array of child 'ObjectIdentity's */ - function findChildren(ObjectIdentityInterface $parentOid, $directChildrenOnly = false); + public function findChildren(ObjectIdentityInterface $parentOid, $directChildrenOnly = false); /** * 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 */ - function findAcl(ObjectIdentityInterface $oid, array $sids = array()); + 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 */ - function findAcls(array $oids, array $sids = array()); + public function findAcls(array $oids, array $sids = array()); } diff --git a/Acl/Model/AuditLoggerInterface.php b/Acl/Model/AuditLoggerInterface.php index 7cab6f1..09bcbb8 100644 --- a/Acl/Model/AuditLoggerInterface.php +++ b/Acl/Model/AuditLoggerInterface.php @@ -25,5 +25,5 @@ interface AuditLoggerInterface * @param Boolean $granted * @param EntryInterface $ace */ - function logIfNeeded($granted, EntryInterface $ace); + public function logIfNeeded($granted, EntryInterface $ace); } diff --git a/Acl/Model/AuditableAclInterface.php b/Acl/Model/AuditableAclInterface.php index 5da593e..14b4c04 100644 --- a/Acl/Model/AuditableAclInterface.php +++ b/Acl/Model/AuditableAclInterface.php @@ -25,7 +25,7 @@ interface AuditableAclInterface extends MutableAclInterface * @param Boolean $auditSuccess * @param Boolean $auditFailure */ - function updateClassAuditing($index, $auditSuccess, $auditFailure); + public function updateClassAuditing($index, $auditSuccess, $auditFailure); /** * Updates auditing for class-field-based ACE @@ -35,7 +35,7 @@ interface AuditableAclInterface extends MutableAclInterface * @param Boolean $auditSuccess * @param Boolean $auditFailure */ - function updateClassFieldAuditing($index, $field, $auditSuccess, $auditFailure); + public function updateClassFieldAuditing($index, $field, $auditSuccess, $auditFailure); /** * Updates auditing for object-based ACE @@ -44,7 +44,7 @@ interface AuditableAclInterface extends MutableAclInterface * @param Boolean $auditSuccess * @param Boolean $auditFailure */ - function updateObjectAuditing($index, $auditSuccess, $auditFailure); + public function updateObjectAuditing($index, $auditSuccess, $auditFailure); /** * Updates auditing for object-field-based ACE @@ -54,5 +54,5 @@ interface AuditableAclInterface extends MutableAclInterface * @param Boolean $auditSuccess * @param Boolean $auditFailure */ - function updateObjectFieldAuditing($index, $field, $auditSuccess, $auditFailure); + public function updateObjectFieldAuditing($index, $field, $auditSuccess, $auditFailure); } diff --git a/Acl/Model/AuditableEntryInterface.php b/Acl/Model/AuditableEntryInterface.php index 40c4484..e957965 100644 --- a/Acl/Model/AuditableEntryInterface.php +++ b/Acl/Model/AuditableEntryInterface.php @@ -23,12 +23,12 @@ interface AuditableEntryInterface extends EntryInterface * * @return Boolean */ - function isAuditFailure(); + public function isAuditFailure(); /** * Whether auditing for successful denies is turned on * * @return Boolean */ - function isAuditSuccess(); + public function isAuditSuccess(); } diff --git a/Acl/Model/DomainObjectInterface.php b/Acl/Model/DomainObjectInterface.php index 50bc4c3..195cb4e 100644 --- a/Acl/Model/DomainObjectInterface.php +++ b/Acl/Model/DomainObjectInterface.php @@ -25,5 +25,5 @@ interface DomainObjectInterface * * @return string */ - function getObjectIdentifier(); + public function getObjectIdentifier(); } diff --git a/Acl/Model/EntryInterface.php b/Acl/Model/EntryInterface.php index 6fe0dc8..98b754c 100644 --- a/Acl/Model/EntryInterface.php +++ b/Acl/Model/EntryInterface.php @@ -26,40 +26,40 @@ interface EntryInterface extends \Serializable * * @return AclInterface */ - function getAcl(); + public function getAcl(); /** * The primary key of this ACE * * @return integer */ - function getId(); + public function getId(); /** * The permission mask of this ACE * * @return integer */ - function getMask(); + public function getMask(); /** * The security identity associated with this ACE * * @return SecurityIdentityInterface */ - function getSecurityIdentity(); + public function getSecurityIdentity(); /** * The strategy for comparing masks * * @return string */ - function getStrategy(); + public function getStrategy(); /** * Returns whether this ACE is granting, or denying * * @return Boolean */ - function isGranting(); + public function isGranting(); } diff --git a/Acl/Model/FieldEntryInterface.php b/Acl/Model/FieldEntryInterface.php index a35ddb4..8382ae1 100644 --- a/Acl/Model/FieldEntryInterface.php +++ b/Acl/Model/FieldEntryInterface.php @@ -23,5 +23,5 @@ interface FieldEntryInterface extends EntryInterface * * @return string */ - function getField(); + public function getField(); } diff --git a/Acl/Model/MutableAclInterface.php b/Acl/Model/MutableAclInterface.php index f84e817..365a779 100644 --- a/Acl/Model/MutableAclInterface.php +++ b/Acl/Model/MutableAclInterface.php @@ -26,7 +26,7 @@ interface MutableAclInterface extends AclInterface * * @param integer $index */ - function deleteClassAce($index); + public function deleteClassAce($index); /** * Deletes a class-field-based ACE @@ -34,14 +34,14 @@ interface MutableAclInterface extends AclInterface * @param integer $index * @param string $field */ - function deleteClassFieldAce($index, $field); + public function deleteClassFieldAce($index, $field); /** * Deletes an object-based ACE * * @param integer $index */ - function deleteObjectAce($index); + public function deleteObjectAce($index); /** * Deletes an object-field-based ACE @@ -49,14 +49,14 @@ interface MutableAclInterface extends AclInterface * @param integer $index * @param string $field */ - function deleteObjectFieldAce($index, $field); + public function deleteObjectFieldAce($index, $field); /** * Returns the primary key of this ACL * * @return integer */ - function getId(); + public function getId(); /** * Inserts a class-based ACE @@ -67,7 +67,7 @@ interface MutableAclInterface extends AclInterface * @param Boolean $granting * @param string $strategy */ - function insertClassAce(SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null); + public function insertClassAce(SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null); /** * Inserts a class-field-based ACE @@ -79,7 +79,7 @@ interface MutableAclInterface extends AclInterface * @param Boolean $granting * @param string $strategy */ - function insertClassFieldAce($field, SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null); + public function insertClassFieldAce($field, SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null); /** * Inserts an object-based ACE @@ -90,7 +90,7 @@ interface MutableAclInterface extends AclInterface * @param Boolean $granting * @param string $strategy */ - function insertObjectAce(SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null); + public function insertObjectAce(SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null); /** * Inserts an object-field-based ACE @@ -102,22 +102,21 @@ interface MutableAclInterface extends AclInterface * @param Boolean $granting * @param string $strategy */ - function insertObjectFieldAce($field, SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null); + public function insertObjectFieldAce($field, SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null); /** * Sets whether entries are inherited * * @param Boolean $boolean */ - function setEntriesInheriting($boolean); + public function setEntriesInheriting($boolean); /** * Sets the parent ACL * * @param AclInterface|null $acl - * @return void */ - function setParentAcl(AclInterface $acl = null); + public function setParentAcl(AclInterface $acl = null); /** * Updates a class-based ACE @@ -126,7 +125,7 @@ interface MutableAclInterface extends AclInterface * @param integer $mask * @param string $strategy if null the strategy should not be changed */ - function updateClassAce($index, $mask, $strategy = null); + public function updateClassAce($index, $mask, $strategy = null); /** * Updates a class-field-based ACE @@ -136,7 +135,7 @@ interface MutableAclInterface extends AclInterface * @param integer $mask * @param string $strategy if null the strategy should not be changed */ - function updateClassFieldAce($index, $field, $mask, $strategy = null); + public function updateClassFieldAce($index, $field, $mask, $strategy = null); /** * Updates an object-based ACE @@ -145,7 +144,7 @@ interface MutableAclInterface extends AclInterface * @param integer $mask * @param string $strategy if null the strategy should not be changed */ - function updateObjectAce($index, $mask, $strategy = null); + public function updateObjectAce($index, $mask, $strategy = null); /** * Updates an object-field-based ACE @@ -155,5 +154,5 @@ interface MutableAclInterface extends AclInterface * @param integer $mask * @param string $strategy if null the strategy should not be changed */ - function updateObjectFieldAce($index, $field, $mask, $strategy = null); + public function updateObjectFieldAce($index, $field, $mask, $strategy = null); } diff --git a/Acl/Model/MutableAclProviderInterface.php b/Acl/Model/MutableAclProviderInterface.php index 04cf237..cb34b72 100644 --- a/Acl/Model/MutableAclProviderInterface.php +++ b/Acl/Model/MutableAclProviderInterface.php @@ -26,7 +26,7 @@ interface MutableAclProviderInterface extends AclProviderInterface * @param ObjectIdentityInterface $oid * @return MutableAclInterface */ - function createAcl(ObjectIdentityInterface $oid); + public function createAcl(ObjectIdentityInterface $oid); /** * Deletes the ACL for a given object identity. @@ -36,7 +36,7 @@ interface MutableAclProviderInterface extends AclProviderInterface * * @param ObjectIdentityInterface $oid */ - function deleteAcl(ObjectIdentityInterface $oid); + public function deleteAcl(ObjectIdentityInterface $oid); /** * Persists any changes which were made to the ACL, or any associated @@ -46,5 +46,5 @@ interface MutableAclProviderInterface extends AclProviderInterface * * @param MutableAclInterface $acl */ - function updateAcl(MutableAclInterface $acl); + public function updateAcl(MutableAclInterface $acl); } diff --git a/Acl/Model/ObjectIdentityInterface.php b/Acl/Model/ObjectIdentityInterface.php index 7e892bf..8ad0eba 100644 --- a/Acl/Model/ObjectIdentityInterface.php +++ b/Acl/Model/ObjectIdentityInterface.php @@ -30,7 +30,7 @@ interface ObjectIdentityInterface * @param ObjectIdentityInterface $identity * @return Boolean */ - function equals(ObjectIdentityInterface $identity); + public function equals(ObjectIdentityInterface $identity); /** * Obtains a unique identifier for this object. The identifier must not be @@ -38,12 +38,12 @@ interface ObjectIdentityInterface * * @return string cannot return null */ - function getIdentifier(); + public function getIdentifier(); /** * Returns a type for the domain object. Typically, this is the PHP class name. * * @return string cannot return null */ - function getType(); + public function getType(); } diff --git a/Acl/Model/ObjectIdentityRetrievalStrategyInterface.php b/Acl/Model/ObjectIdentityRetrievalStrategyInterface.php index e53c3da..b0f7f78 100644 --- a/Acl/Model/ObjectIdentityRetrievalStrategyInterface.php +++ b/Acl/Model/ObjectIdentityRetrievalStrategyInterface.php @@ -24,5 +24,5 @@ interface ObjectIdentityRetrievalStrategyInterface * @param object $domainObject * @return ObjectIdentityInterface */ - function getObjectIdentity($domainObject); + public function getObjectIdentity($domainObject); } diff --git a/Acl/Model/PermissionGrantingStrategyInterface.php b/Acl/Model/PermissionGrantingStrategyInterface.php index 7afdfac..7f8f81b 100644 --- a/Acl/Model/PermissionGrantingStrategyInterface.php +++ b/Acl/Model/PermissionGrantingStrategyInterface.php @@ -27,7 +27,7 @@ interface PermissionGrantingStrategyInterface * @param Boolean $administrativeMode * @return Boolean */ - function isGranted(AclInterface $acl, array $masks, array $sids, $administrativeMode = false); + public function isGranted(AclInterface $acl, array $masks, array $sids, $administrativeMode = false); /** * Determines whether access to a domain object's field is to be granted @@ -40,5 +40,5 @@ interface PermissionGrantingStrategyInterface * * @return Boolean */ - function isFieldGranted(AclInterface $acl, $field, array $masks, array $sids, $administrativeMode = false); + public function isFieldGranted(AclInterface $acl, $field, array $masks, array $sids, $administrativeMode = false); } diff --git a/Acl/Model/SecurityIdentityInterface.php b/Acl/Model/SecurityIdentityInterface.php index 5bf6189..0a24a54 100644 --- a/Acl/Model/SecurityIdentityInterface.php +++ b/Acl/Model/SecurityIdentityInterface.php @@ -26,5 +26,5 @@ interface SecurityIdentityInterface * * @param SecurityIdentityInterface $identity */ - function equals(SecurityIdentityInterface $identity); + public function equals(SecurityIdentityInterface $identity); } diff --git a/Acl/Model/SecurityIdentityRetrievalStrategyInterface.php b/Acl/Model/SecurityIdentityRetrievalStrategyInterface.php index 3bbbaa4..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 */ - function getSecurityIdentities(TokenInterface $token); + public function getSecurityIdentities(TokenInterface $token); } diff --git a/Acl/Permission/MaskBuilder.php b/Acl/Permission/MaskBuilder.php index 6921558..017e7c0 100644 --- a/Acl/Permission/MaskBuilder.php +++ b/Acl/Permission/MaskBuilder.php @@ -73,6 +73,8 @@ class MaskBuilder * Constructor * * @param integer $mask optional; defaults to 0 + * + * @throws \InvalidArgumentException */ public function __construct($mask = 0) { @@ -87,7 +89,10 @@ class MaskBuilder * Adds a mask to the permission * * @param mixed $mask + * * @return MaskBuilder + * + * @throws \InvalidArgumentException */ public function add($mask) { @@ -140,7 +145,10 @@ class MaskBuilder * Removes a mask from the permission * * @param mixed $mask + * * @return MaskBuilder + * + * @throws \InvalidArgumentException */ public function remove($mask) { @@ -175,7 +183,7 @@ class MaskBuilder * @throws \RuntimeException * @return string */ - static public function getCode($mask) + public static function getCode($mask) { if (!is_int($mask)) { throw new \InvalidArgumentException('$mask must be an integer.'); diff --git a/Acl/Permission/PermissionMapInterface.php b/Acl/Permission/PermissionMapInterface.php index c2e49d5..44c15cc 100644 --- a/Acl/Permission/PermissionMapInterface.php +++ b/Acl/Permission/PermissionMapInterface.php @@ -28,7 +28,7 @@ interface PermissionMapInterface * @param object $object * @return array may return null if permission/object combination is not supported */ - function getMasks($permission, $object); + public function getMasks($permission, $object); /** * Whether this map contains the given permission @@ -36,5 +36,5 @@ interface PermissionMapInterface * @param string $permission * @return Boolean */ - function contains($permission); + public function contains($permission); } diff --git a/Acl/Resources/bin/generateSql.php b/Acl/Resources/bin/generateSql.php index 25ded7a..4a5ca05 100644 --- a/Acl/Resources/bin/generateSql.php +++ b/Acl/Resources/bin/generateSql.php @@ -9,14 +9,14 @@ * file that was distributed with this source code. */ -require_once __DIR__.'/../../../../ClassLoader/UniversalClassLoader.php'; +require_once __DIR__.'/../../../../ClassLoader/ClassLoader.php'; -use Symfony\Component\ClassLoader\UniversalClassLoader; +use Symfony\Component\ClassLoader\ClassLoader; use Symfony\Component\Finder\Finder; use Symfony\Component\Security\Acl\Dbal\Schema; -$loader = new UniversalClassLoader(); -$loader->registerNamespaces(array( +$loader = new ClassLoader(); +$loader->addPrefixes(array( 'Symfony' => __DIR__.'/../../../../../..', 'Doctrine\\Common' => __DIR__.'/../../../../../../../vendor/doctrine-common/lib', 'Doctrine\\DBAL\\Migrations' => __DIR__.'/../../../../../../../vendor/doctrine-migrations/lib', @@ -25,7 +25,6 @@ $loader->registerNamespaces(array( )); $loader->register(); - $schema = new Schema(array( 'class_table_name' => 'acl_classes', 'entry_table_name' => 'acl_entries', diff --git a/Acl/Voter/AclVoter.php b/Acl/Voter/AclVoter.php index 456c434..5e9aee6 100644 --- a/Acl/Voter/AclVoter.php +++ b/Acl/Voter/AclVoter.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Security\Acl\Voter; -use Symfony\Component\HttpKernel\Log\LoggerInterface; +use Psr\Log\LoggerInterface; use Symfony\Component\Security\Acl\Exception\NoAceFoundException; use Symfony\Component\Security\Acl\Exception\AclNotFoundException; use Symfony\Component\Security\Acl\Model\AclProviderInterface; diff --git a/CHANGELOG.md b/CHANGELOG.md index 2389ac3..82c4312 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,16 @@ 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 + * added BCrypt password encoder + 2.1.0 ----- @@ -20,3 +30,13 @@ CHANGELOG * `ObjectIdentity::fromDomainObject`, `UserSecurityIdentity::fromAccount` and `UserSecurityIdentity::fromToken` now return correct identities for proxies objects (e.g. Doctrine proxies) + * [BC BREAK] moved the default authentication success and failure handling to + separate classes. The order of arguments in the constructor of the + `AbstractAuthenticationListener` has changed. + * [BC BREAK] moved the default logout success handling to a separate class. The + order of arguments in the constructor of `LogoutListener` has changed. + * [BC BREAK] The constructor of `AuthenticationException` and all child + classes now matches the constructor of `\Exception`. The extra information + getters and setters are removed. There are now dedicated getters/setters for + token (`AuthenticationException'), user (`AccountStatusException`) and + username (`UsernameNotFoundException`). diff --git a/Core/Authentication/AuthenticationManagerInterface.php b/Core/Authentication/AuthenticationManagerInterface.php index 36cdc92..d8f4716 100644 --- a/Core/Authentication/AuthenticationManagerInterface.php +++ b/Core/Authentication/AuthenticationManagerInterface.php @@ -31,5 +31,5 @@ interface AuthenticationManagerInterface * * @throws AuthenticationException if the authentication fails */ - function authenticate(TokenInterface $token); + public function authenticate(TokenInterface $token); } diff --git a/Core/Authentication/AuthenticationProviderManager.php b/Core/Authentication/AuthenticationProviderManager.php index 7ca46c0..8b7474b 100644 --- a/Core/Authentication/AuthenticationProviderManager.php +++ b/Core/Authentication/AuthenticationProviderManager.php @@ -39,6 +39,8 @@ class AuthenticationProviderManager implements AuthenticationManagerInterface * * @param AuthenticationProviderInterface[] $providers An array of AuthenticationProviderInterface instances * @param Boolean $eraseCredentials Whether to erase credentials after authentication or not + * + * @throws \InvalidArgumentException */ public function __construct(array $providers, $eraseCredentials = true) { @@ -75,7 +77,7 @@ class AuthenticationProviderManager implements AuthenticationManagerInterface break; } } catch (AccountStatusException $e) { - $e->setExtraInformation($token); + $e->setToken($token); throw $e; } catch (AuthenticationException $e) { @@ -103,7 +105,7 @@ class AuthenticationProviderManager implements AuthenticationManagerInterface $this->eventDispatcher->dispatch(AuthenticationEvents::AUTHENTICATION_FAILURE, new AuthenticationFailureEvent($token, $lastException)); } - $lastException->setExtraInformation($token); + $lastException->setToken($token); throw $lastException; } diff --git a/Core/Authentication/AuthenticationTrustResolverInterface.php b/Core/Authentication/AuthenticationTrustResolverInterface.php index adcef3c..ac07db0 100644 --- a/Core/Authentication/AuthenticationTrustResolverInterface.php +++ b/Core/Authentication/AuthenticationTrustResolverInterface.php @@ -30,7 +30,7 @@ interface AuthenticationTrustResolverInterface * * @return Boolean */ - function isAnonymous(TokenInterface $token = null); + public function isAnonymous(TokenInterface $token = null); /** * Resolves whether the passed token implementation is authenticated @@ -40,7 +40,7 @@ interface AuthenticationTrustResolverInterface * * @return Boolean */ - function isRememberMe(TokenInterface $token = null); + public function isRememberMe(TokenInterface $token = null); /** * Resolves whether the passed token implementation is fully authenticated. @@ -49,5 +49,5 @@ interface AuthenticationTrustResolverInterface * * @return Boolean */ - function isFullFledged(TokenInterface $token = null); + public function isFullFledged(TokenInterface $token = null); } diff --git a/Core/Authentication/Provider/AuthenticationProviderInterface.php b/Core/Authentication/Provider/AuthenticationProviderInterface.php index 956adf1..f63a924 100644 --- a/Core/Authentication/Provider/AuthenticationProviderInterface.php +++ b/Core/Authentication/Provider/AuthenticationProviderInterface.php @@ -31,5 +31,5 @@ interface AuthenticationProviderInterface extends AuthenticationManagerInterface * * @return Boolean true if the implementation supports the Token, false otherwise */ - function supports(TokenInterface $token); + public function supports(TokenInterface $token); } diff --git a/Core/Authentication/Provider/DaoAuthenticationProvider.php b/Core/Authentication/Provider/DaoAuthenticationProvider.php index f22045f..a9a2205 100644 --- a/Core/Authentication/Provider/DaoAuthenticationProvider.php +++ b/Core/Authentication/Provider/DaoAuthenticationProvider.php @@ -88,9 +88,12 @@ class DaoAuthenticationProvider extends UserAuthenticationProvider return $user; } catch (UsernameNotFoundException $notFound) { + $notFound->setUsername($username); throw $notFound; } catch (\Exception $repositoryProblem) { - throw new AuthenticationServiceException($repositoryProblem->getMessage(), $token, 0, $repositoryProblem); + $ex = new AuthenticationServiceException($repositoryProblem->getMessage(), 0, $repositoryProblem); + $ex->setToken($token); + throw $ex; } } } diff --git a/Core/Authentication/Provider/UserAuthenticationProvider.php b/Core/Authentication/Provider/UserAuthenticationProvider.php index 32d7971..626f50b 100644 --- a/Core/Authentication/Provider/UserAuthenticationProvider.php +++ b/Core/Authentication/Provider/UserAuthenticationProvider.php @@ -37,6 +37,8 @@ abstract class UserAuthenticationProvider implements AuthenticationProviderInter * @param UserCheckerInterface $userChecker An UserCheckerInterface interface * @param string $providerKey A provider key * @param Boolean $hideUserNotFoundExceptions Whether to hide user not found exception or not + * + * @throws \InvalidArgumentException */ public function __construct(UserCheckerInterface $userChecker, $providerKey, $hideUserNotFoundExceptions = true) { @@ -69,6 +71,7 @@ abstract class UserAuthenticationProvider implements AuthenticationProviderInter if ($this->hideUserNotFoundExceptions) { throw new BadCredentialsException('Bad credentials', 0, $notFound); } + $notFound->setUsername($username); throw $notFound; } diff --git a/Core/Authentication/RememberMe/PersistentToken.php b/Core/Authentication/RememberMe/PersistentToken.php index a31c878..f3f6858 100644 --- a/Core/Authentication/RememberMe/PersistentToken.php +++ b/Core/Authentication/RememberMe/PersistentToken.php @@ -27,11 +27,13 @@ final class PersistentToken implements PersistentTokenInterface /** * Constructor * - * @param string $class - * @param string $username - * @param string $series - * @param string $tokenValue - * @param DateTime $lastUsed + * @param string $class + * @param string $username + * @param string $series + * @param string $tokenValue + * @param \DateTime $lastUsed + * + * @throws \InvalidArgumentException */ public function __construct($class, $username, $series, $tokenValue, \DateTime $lastUsed) { diff --git a/Core/Authentication/RememberMe/PersistentTokenInterface.php b/Core/Authentication/RememberMe/PersistentTokenInterface.php index 38acbc3..6e9d891 100644 --- a/Core/Authentication/RememberMe/PersistentTokenInterface.php +++ b/Core/Authentication/RememberMe/PersistentTokenInterface.php @@ -23,29 +23,29 @@ interface PersistentTokenInterface * Returns the class of the user * @return string */ - function getClass(); + public function getClass(); /** * Returns the username * @return string */ - function getUsername(); + public function getUsername(); /** * Returns the series * @return string */ - function getSeries(); + public function getSeries(); /** * Returns the token value * @return string */ - function getTokenValue(); + public function getTokenValue(); /** * Returns the last time the cookie was used * @return \DateTime */ - function getLastUsed(); + public function getLastUsed(); } diff --git a/Core/Authentication/RememberMe/TokenProviderInterface.php b/Core/Authentication/RememberMe/TokenProviderInterface.php index db40a1c..0c6f75e 100644 --- a/Core/Authentication/RememberMe/TokenProviderInterface.php +++ b/Core/Authentication/RememberMe/TokenProviderInterface.php @@ -27,28 +27,28 @@ interface TokenProviderInterface * * @return PersistentTokenInterface */ - function loadTokenBySeries($series); + public function loadTokenBySeries($series); /** * Deletes all tokens belonging to series. * * @param string $series */ - function deleteTokenBySeries($series); + public function deleteTokenBySeries($series); /** * Updates the token according to this data. * - * @param string $series - * @param string $tokenValue - * @param DateTime $lastUsed + * @param string $series + * @param string $tokenValue + * @param \DateTime $lastUsed */ - function updateToken($series, $tokenValue, \DateTime $lastUsed); + public function updateToken($series, $tokenValue, \DateTime $lastUsed); /** * Creates a new token. * * @param PersistentTokenInterface $token */ - function createNewToken(PersistentTokenInterface $token); + public function createNewToken(PersistentTokenInterface $token); } diff --git a/Core/Authentication/Token/AbstractToken.php b/Core/Authentication/Token/AbstractToken.php index ed6e8de..f21aa76 100644 --- a/Core/Authentication/Token/AbstractToken.php +++ b/Core/Authentication/Token/AbstractToken.php @@ -33,7 +33,9 @@ abstract class AbstractToken implements TokenInterface /** * Constructor. * - * @param Role[] $roles An array of roles + * @param RoleInterface[] $roles An array of roles + * + * @throws \InvalidArgumentException */ 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/RememberMeToken.php b/Core/Authentication/Token/RememberMeToken.php index de50e5c..6f3d821 100644 --- a/Core/Authentication/Token/RememberMeToken.php +++ b/Core/Authentication/Token/RememberMeToken.php @@ -29,6 +29,8 @@ class RememberMeToken extends AbstractToken * @param UserInterface $user * @param string $providerKey * @param string $key + * + * @throws \InvalidArgumentException */ public function __construct(UserInterface $user, $providerKey, $key) { diff --git a/Core/Authentication/Token/TokenInterface.php b/Core/Authentication/Token/TokenInterface.php index 3dafccc..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. * @@ -26,21 +28,21 @@ interface TokenInterface extends \Serializable * * @return string */ - function __toString(); + public function __toString(); /** * Returns the user roles. * - * @return Role[] An array of Role instances. + * @return RoleInterface[] An array of RoleInterface instances. */ - function getRoles(); + public function getRoles(); /** * Returns the user credentials. * * @return mixed The user credentials */ - function getCredentials(); + public function getCredentials(); /** * Returns a user representation. @@ -48,54 +50,54 @@ interface TokenInterface extends \Serializable * @return mixed either returns an object which implements __toString(), or * a primitive string is returned. */ - function getUser(); + public function getUser(); /** * Sets a user. * * @param mixed $user */ - function setUser($user); + public function setUser($user); /** * Returns the username. * * @return string */ - function getUsername(); + public function getUsername(); /** * Returns whether the user is authenticated or not. * * @return Boolean true if the token has been authenticated, false otherwise */ - function isAuthenticated(); + public function isAuthenticated(); /** * Sets the authenticated flag. * * @param Boolean $isAuthenticated The authenticated flag */ - function setAuthenticated($isAuthenticated); + public function setAuthenticated($isAuthenticated); /** * Removes sensitive information from the token. */ - function eraseCredentials(); + public function eraseCredentials(); /** * Returns the token attributes. * * @return array The token attributes */ - function getAttributes(); + public function getAttributes(); /** * Sets the token attributes. * * @param array $attributes The token attributes */ - function setAttributes(array $attributes); + public function setAttributes(array $attributes); /** * Returns true if the attribute exists. @@ -104,7 +106,7 @@ interface TokenInterface extends \Serializable * * @return Boolean true if the attribute exists, false otherwise */ - function hasAttribute($name); + public function hasAttribute($name); /** * Returns an attribute value. @@ -115,7 +117,7 @@ interface TokenInterface extends \Serializable * * @throws \InvalidArgumentException When attribute doesn't exist for this token */ - function getAttribute($name); + public function getAttribute($name); /** * Sets an attribute. @@ -123,5 +125,5 @@ interface TokenInterface extends \Serializable * @param string $name The attribute name * @param mixed $value The attribute value */ - function setAttribute($name, $value); + public function setAttribute($name, $value); } 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/AuthenticationEvents.php b/Core/AuthenticationEvents.php index 1e0e6ff..90b7142 100644 --- a/Core/AuthenticationEvents.php +++ b/Core/AuthenticationEvents.php @@ -13,7 +13,26 @@ namespace Symfony\Component\Security\Core; final class AuthenticationEvents { + /** + * The AUTHENTICATION_SUCCESS event occurs after a user is authenticated + * by one provider. + * + * The event listener method receives a + * Symfony\Component\Security\Core\Event\AuthenticationEvent instance. + * + * @var string + */ const AUTHENTICATION_SUCCESS = 'security.authentication.success'; + /** + * The AUTHENTICATION_FAILURE event occurs after a user cannot be + * authenticated by any of the providers. + * + * The event listener method receives a + * Symfony\Component\Security\Core\Event\AuthenticationFailureEvent + * instance. + * + * @var string + */ const AUTHENTICATION_FAILURE = 'security.authentication.failure'; } diff --git a/Core/Authorization/AccessDecisionManager.php b/Core/Authorization/AccessDecisionManager.php index a8bb5cf..6028c42 100644 --- a/Core/Authorization/AccessDecisionManager.php +++ b/Core/Authorization/AccessDecisionManager.php @@ -34,6 +34,8 @@ class AccessDecisionManager implements AccessDecisionManagerInterface * @param string $strategy The vote strategy * @param Boolean $allowIfAllAbstainDecisions Whether to grant access if all voters abstained or not * @param Boolean $allowIfEqualGrantedDeniedDecisions Whether to grant access if result are equals + * + * @throws \InvalidArgumentException */ public function __construct(array $voters, $strategy = 'affirmative', $allowIfAllAbstainDecisions = false, $allowIfEqualGrantedDeniedDecisions = true) { diff --git a/Core/Authorization/AccessDecisionManagerInterface.php b/Core/Authorization/AccessDecisionManagerInterface.php index 648047a..742ea74 100644 --- a/Core/Authorization/AccessDecisionManagerInterface.php +++ b/Core/Authorization/AccessDecisionManagerInterface.php @@ -29,7 +29,7 @@ interface AccessDecisionManagerInterface * * @return Boolean true if the access is granted, false otherwise */ - function decide(TokenInterface $token, array $attributes, $object = null); + public function decide(TokenInterface $token, array $attributes, $object = null); /** * Checks if the access decision manager supports the given attribute. @@ -38,7 +38,7 @@ interface AccessDecisionManagerInterface * * @return Boolean true if this decision manager supports the attribute, false otherwise */ - function supportsAttribute($attribute); + public function supportsAttribute($attribute); /** * Checks if the access decision manager supports the given class. @@ -47,5 +47,5 @@ interface AccessDecisionManagerInterface * * @return true if this decision manager can process the class */ - function supportsClass($class); + public function supportsClass($class); } diff --git a/Core/Authorization/Voter/VoterInterface.php b/Core/Authorization/Voter/VoterInterface.php index 41d9e64..1fc93e5 100644 --- a/Core/Authorization/Voter/VoterInterface.php +++ b/Core/Authorization/Voter/VoterInterface.php @@ -31,7 +31,7 @@ interface VoterInterface * * @return Boolean true if this Voter supports the attribute, false otherwise */ - function supportsAttribute($attribute); + public function supportsAttribute($attribute); /** * Checks if the voter supports the given class. @@ -40,7 +40,7 @@ interface VoterInterface * * @return true if this Voter can process the class */ - function supportsClass($class); + public function supportsClass($class); /** * Returns the vote for the given parameters. @@ -54,5 +54,5 @@ interface VoterInterface * * @return integer either ACCESS_GRANTED, ACCESS_ABSTAIN, or ACCESS_DENIED */ - function vote(TokenInterface $token, $object, array $attributes); + public function vote(TokenInterface $token, $object, array $attributes); } diff --git a/Core/Encoder/BCryptPasswordEncoder.php b/Core/Encoder/BCryptPasswordEncoder.php new file mode 100644 index 0000000..1b7572d --- /dev/null +++ b/Core/Encoder/BCryptPasswordEncoder.php @@ -0,0 +1,148 @@ +<?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\Core\Encoder; + +use Symfony\Component\Security\Core\Encoder\BasePasswordEncoder; +use Symfony\Component\Security\Core\Util\SecureRandomInterface; + +/** + * @author Elnur Abdurrakhimov <elnur@elnur.pro> + * @author Terje Bråten <terje@braten.be> + */ +class BCryptPasswordEncoder extends BasePasswordEncoder +{ + /** + * @var SecureRandomInterface + */ + private $secureRandom; + + /** + * @var string + */ + private $cost; + + private static $prefix = null; + + /** + * Constructor. + * + * @param SecureRandomInterface $secureRandom A SecureRandomInterface instance + * @param integer $cost The algorithmic cost that should be used + * + * @throws \InvalidArgumentException if cost is out of range + */ + public function __construct(SecureRandomInterface $secureRandom, $cost) + { + $this->secureRandom = $secureRandom; + + $cost = (int) $cost; + if ($cost < 4 || $cost > 31) { + throw new \InvalidArgumentException('Cost must be in the range of 4-31.'); + } + $this->cost = sprintf('%02d', $cost); + + if (!self::$prefix) { + self::$prefix = '$'.(version_compare(phpversion(), '5.3.7', '>=') ? '2y' : '2a').'$'; + } + } + + /** + * {@inheritdoc} + */ + public function encodePassword($raw, $salt) + { + if (function_exists('password_hash')) { + return password_hash($raw, PASSWORD_BCRYPT, array('cost' => $this->cost)); + } + + $salt = self::$prefix.$this->cost.'$'.$this->encodeSalt($this->getRawSalt()); + $encoded = crypt($raw, $salt); + if (!is_string($encoded) || strlen($encoded) <= 13) { + return false; + } + + return $encoded; + } + + /** + * {@inheritdoc} + */ + public function isPasswordValid($encoded, $raw, $salt) + { + if (function_exists('password_verify')) { + return password_verify($raw, $encoded); + } + + $crypted = crypt($raw, $encoded); + if (strlen($crypted) <= 13) { + return false; + } + + return $this->comparePasswords($encoded, $crypted); + } + + /** + * Encodes the salt to be used by Bcrypt. + * + * The blowfish/bcrypt algorithm used by PHP crypt expects a different + * set and order of characters than the usual base64_encode function. + * Regular b64: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ + * Bcrypt b64: ./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 + * We care because the last character in our encoded string will + * only represent 2 bits. While two known implementations of + * bcrypt will happily accept and correct a salt string which + * has the 4 unused bits set to non-zero, we do not want to take + * chances and we also do not want to waste an additional byte + * of entropy. + * + * @param bytes $random a string of 16 random bytes + * + * @return string Properly encoded salt to use with php crypt function + * + * @throws \InvalidArgumentException if string of random bytes is too short + */ + protected function encodeSalt($random) + { + $len = strlen($random); + if ($len < 16) { + throw new \InvalidArgumentException('The bcrypt salt needs 16 random bytes.'); + } + if ($len > 16) { + $random = substr($random, 0, 16); + } + + $base64raw = str_replace('+', '.', base64_encode($random)); + $salt128bit = substr($base64raw, 0, 21); + $lastchar = substr($base64raw, 21, 1); + $lastchar = strtr($lastchar, 'AQgw', '.Oeu'); + $salt128bit .= $lastchar; + + return $salt128bit; + } + + /** + * @return bytes 16 random bytes to be used in the salt + */ + protected function getRawSalt() + { + $rawSalt = false; + $numBytes = 16; + if (function_exists('mcrypt_create_iv')) { + $rawSalt = mcrypt_create_iv($numBytes, MCRYPT_DEV_URANDOM); + } + if (!$rawSalt) { + $rawSalt = $this->secureRandom->nextBytes($numBytes); + } + + return $rawSalt; + } +} diff --git a/Core/Encoder/BasePasswordEncoder.php b/Core/Encoder/BasePasswordEncoder.php index ae1c7d4..c26c9ce 100644 --- a/Core/Encoder/BasePasswordEncoder.php +++ b/Core/Encoder/BasePasswordEncoder.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Security\Core\Encoder; +use Symfony\Component\Security\Core\Util\StringUtils; + /** * BasePasswordEncoder is the base class for all password encoders. * @@ -50,6 +52,8 @@ abstract class BasePasswordEncoder implements PasswordEncoderInterface * @param string $salt the salt to be used * * @return string a merged password and salt + * + * @throws \InvalidArgumentException */ protected function mergePasswordAndSalt($password, $salt) { @@ -77,15 +81,6 @@ abstract class BasePasswordEncoder implements PasswordEncoderInterface */ protected function comparePasswords($password1, $password2) { - if (strlen($password1) !== strlen($password2)) { - return false; - } - - $result = 0; - for ($i = 0; $i < strlen($password1); $i++) { - $result |= ord($password1[$i]) ^ ord($password2[$i]); - } - - return 0 === $result; + return StringUtils::equals($password1, $password2); } } diff --git a/Core/Encoder/EncoderFactory.php b/Core/Encoder/EncoderFactory.php index 7d34cc7..8bad61f 100644 --- a/Core/Encoder/EncoderFactory.php +++ b/Core/Encoder/EncoderFactory.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Security\Core\Encoder; -use Symfony\Component\Security\Core\User\UserInterface; - /** * A generic encoder factory implementation * @@ -53,6 +51,8 @@ class EncoderFactory implements EncoderFactoryInterface * @param array $config * * @return PasswordEncoderInterface + * + * @throws \InvalidArgumentException */ private function createEncoder(array $config) { diff --git a/Core/Encoder/EncoderFactoryInterface.php b/Core/Encoder/EncoderFactoryInterface.php index 125e57b..2b9834b 100644 --- a/Core/Encoder/EncoderFactoryInterface.php +++ b/Core/Encoder/EncoderFactoryInterface.php @@ -23,11 +23,11 @@ interface EncoderFactoryInterface /** * Returns the password encoder to use for the given account. * - * @param UserInterface|string $user A UserInterface instance of a class name + * @param UserInterface|string $user A UserInterface instance or a class name * * @return PasswordEncoderInterface * * @throws \RuntimeException when no password encoder could be found for the user */ - function getEncoder($user); + public function getEncoder($user); } diff --git a/Core/Encoder/PasswordEncoderInterface.php b/Core/Encoder/PasswordEncoderInterface.php index dae6c69..78b4e42 100644 --- a/Core/Encoder/PasswordEncoderInterface.php +++ b/Core/Encoder/PasswordEncoderInterface.php @@ -26,7 +26,7 @@ interface PasswordEncoderInterface * * @return string The encoded password */ - function encodePassword($raw, $salt); + public function encodePassword($raw, $salt); /** * Checks a raw password against an encoded password. @@ -37,5 +37,5 @@ interface PasswordEncoderInterface * * @return Boolean true if the password is valid, false otherwise */ - function isPasswordValid($encoded, $raw, $salt); + public function isPasswordValid($encoded, $raw, $salt); } diff --git a/Core/Encoder/Pbkdf2PasswordEncoder.php b/Core/Encoder/Pbkdf2PasswordEncoder.php new file mode 100644 index 0000000..656545f --- /dev/null +++ b/Core/Encoder/Pbkdf2PasswordEncoder.php @@ -0,0 +1,97 @@ +<?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\Core\Encoder; + +/** + * Pbkdf2PasswordEncoder uses the PBKDF2 (Password-Based Key Derivation Function 2). + * + * Providing a high level of Cryptographic security, + * PBKDF2 is recommended by the National Institute of Standards and Technology (NIST). + * + * But also warrants a warning, using PBKDF2 (with a high number of iterations) slows down the process. + * PBKDF2 should be used with caution and care. + * + * @author Sebastiaan Stok <s.stok@rollerscapes.net> + * @author Andrew Johnson + * @author Fabien Potencier <fabien@symfony.com> + */ +class Pbkdf2PasswordEncoder extends BasePasswordEncoder +{ + private $algorithm; + private $encodeHashAsBase64; + private $iterations; + private $length; + + /** + * Constructor. + * + * @param string $algorithm The digest algorithm to use + * @param Boolean $encodeHashAsBase64 Whether to base64 encode the password hash + * @param integer $iterations The number of iterations to use to stretch the password hash + * @param integer $length Length of derived key to create + */ + public function __construct($algorithm = 'sha512', $encodeHashAsBase64 = true, $iterations = 1000, $length = 40) + { + $this->algorithm = $algorithm; + $this->encodeHashAsBase64 = $encodeHashAsBase64; + $this->iterations = $iterations; + $this->length = $length; + } + + /** + * {@inheritdoc} + * + * @throws \LogicException when the algorithm is not supported + */ + public function encodePassword($raw, $salt) + { + if (!in_array($this->algorithm, hash_algos(), true)) { + throw new \LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm)); + } + + if (function_exists('hash_pbkdf2')) { + $digest = hash_pbkdf2($this->algorithm, $raw, $salt, $this->iterations, $this->length, true); + } else { + $digest = $this->hashPbkdf2($this->algorithm, $raw, $salt, $this->iterations, $this->length); + } + + return $this->encodeHashAsBase64 ? base64_encode($digest) : bin2hex($digest); + } + + /** + * {@inheritdoc} + */ + public function isPasswordValid($encoded, $raw, $salt) + { + return $this->comparePasswords($encoded, $this->encodePassword($raw, $salt)); + } + + private function hashPbkdf2($algorithm, $password, $salt, $iterations, $length = 0) + { + // Number of blocks needed to create the derived key + $blocks = ceil($length / strlen(hash($algorithm, null, true))); + $digest = ''; + + for ($i = 1; $i <= $blocks; $i++) { + $ib = $block = hash_hmac($algorithm, $salt . pack('N', $i), $password, true); + + // Iterations + for ($j = 1; $j < $iterations; $j++) { + $ib ^= ($block = hash_hmac($algorithm, $block, $password, true)); + } + + $digest .= $ib; + } + + return substr($digest, 0, $this->length); + } +} diff --git a/Core/Exception/AccountExpiredException.php b/Core/Exception/AccountExpiredException.php index f899b1b..a5618ce 100644 --- a/Core/Exception/AccountExpiredException.php +++ b/Core/Exception/AccountExpiredException.php @@ -15,7 +15,15 @@ namespace Symfony\Component\Security\Core\Exception; * AccountExpiredException is thrown when the user account has expired. * * @author Fabien Potencier <fabien@symfony.com> + * @author Alexander <iam.asm89@gmail.com> */ class AccountExpiredException extends AccountStatusException { + /** + * {@inheritDoc} + */ + public function getMessageKey() + { + return 'Account has expired.'; + } } diff --git a/Core/Exception/AccountStatusException.php b/Core/Exception/AccountStatusException.php index 958f584..7819e4d 100644 --- a/Core/Exception/AccountStatusException.php +++ b/Core/Exception/AccountStatusException.php @@ -11,12 +11,57 @@ namespace Symfony\Component\Security\Core\Exception; +use Symfony\Component\Security\Core\User\UserInterface; + /** * AccountStatusException is the base class for authentication exceptions * caused by the user account status. * * @author Fabien Potencier <fabien@symfony.com> + * @author Alexander <iam.asm89@gmail.com> */ abstract class AccountStatusException extends AuthenticationException { + private $user; + + /** + * Get the user. + * + * @return UserInterface + */ + public function getUser() + { + return $this->user; + } + + /** + * Set the user. + * + * @param UserInterface $user + */ + public function setUser(UserInterface $user) + { + $this->user = $user; + } + + /** + * {@inheritDoc} + */ + public function serialize() + { + return serialize(array( + $this->user, + parent::serialize(), + )); + } + + /** + * {@inheritDoc} + */ + public function unserialize($str) + { + list($this->user, $parentData) = unserialize($str); + + parent::unserialize($parentData); + } } diff --git a/Core/Exception/AuthenticationCredentialsNotFoundException.php b/Core/Exception/AuthenticationCredentialsNotFoundException.php index 16686ad..633b2be 100644 --- a/Core/Exception/AuthenticationCredentialsNotFoundException.php +++ b/Core/Exception/AuthenticationCredentialsNotFoundException.php @@ -16,7 +16,15 @@ namespace Symfony\Component\Security\Core\Exception; * because no Token is available. * * @author Fabien Potencier <fabien@symfony.com> + * @author Alexander <iam.asm89@gmail.com> */ class AuthenticationCredentialsNotFoundException extends AuthenticationException { + /** + * {@inheritDoc} + */ + public function getMessageKey() + { + return 'Authentication credentials could not be found.'; + } } diff --git a/Core/Exception/AuthenticationException.php b/Core/Exception/AuthenticationException.php index 074dad0..2b897c2 100644 --- a/Core/Exception/AuthenticationException.php +++ b/Core/Exception/AuthenticationException.php @@ -11,36 +11,42 @@ namespace Symfony\Component\Security\Core\Exception; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; + /** * AuthenticationException is the base class for all authentication exceptions. * * @author Fabien Potencier <fabien@symfony.com> + * @author Alexander <iam.asm89@gmail.com> */ class AuthenticationException extends \RuntimeException implements \Serializable { - private $extraInformation; - - public function __construct($message, $extraInformation = null, $code = 0, \Exception $previous = null) - { - parent::__construct($message, $code, $previous); + private $token; - $this->extraInformation = $extraInformation; - } - - public function getExtraInformation() + /** + * Get the token. + * + * @return TokenInterface + */ + public function getToken() { - return $this->extraInformation; + return $this->token; } - public function setExtraInformation($extraInformation) + /** + * Set the token. + * + * @param TokenInterface $token + */ + public function setToken(TokenInterface $token) { - $this->extraInformation = $extraInformation; + $this->token = $token; } public function serialize() { return serialize(array( - $this->extraInformation, + $this->token, $this->code, $this->message, $this->file, @@ -51,11 +57,31 @@ class AuthenticationException extends \RuntimeException implements \Serializable public function unserialize($str) { list( - $this->extraInformation, + $this->token, $this->code, $this->message, $this->file, $this->line ) = unserialize($str); } + + /** + * Message key to be used by the translation component. + * + * @return string + */ + public function getMessageKey() + { + return 'An authentication exception occurred.'; + } + + /** + * Message data to be used by the translation component. + * + * @return array + */ + public function getMessageData() + { + return array(); + } } diff --git a/Core/Exception/AuthenticationServiceException.php b/Core/Exception/AuthenticationServiceException.php index 5b32d81..758a4f0 100644 --- a/Core/Exception/AuthenticationServiceException.php +++ b/Core/Exception/AuthenticationServiceException.php @@ -15,7 +15,15 @@ namespace Symfony\Component\Security\Core\Exception; * AuthenticationServiceException is thrown when an authentication request could not be processed due to a system problem. * * @author Fabien Potencier <fabien@symfony.com> + * @author Alexander <iam.asm89@gmail.com> */ class AuthenticationServiceException extends AuthenticationException { + /** + * {@inheritDoc} + */ + public function getMessageKey() + { + return 'Authentication request could not be processed due to a system problem.'; + } } diff --git a/Core/Exception/BadCredentialsException.php b/Core/Exception/BadCredentialsException.php index 2eae5b8..5deecca 100644 --- a/Core/Exception/BadCredentialsException.php +++ b/Core/Exception/BadCredentialsException.php @@ -15,11 +15,15 @@ namespace Symfony\Component\Security\Core\Exception; * BadCredentialsException is thrown when the user credentials are invalid. * * @author Fabien Potencier <fabien@symfony.com> + * @author Alexander <iam.asm89@gmail.com> */ class BadCredentialsException extends AuthenticationException { - public function __construct($message, $code = 0, \Exception $previous = null) + /** + * {@inheritDoc} + */ + public function getMessageKey() { - parent::__construct($message, null, $code, $previous); + return 'Invalid credentials.'; } } diff --git a/Core/Exception/CookieTheftException.php b/Core/Exception/CookieTheftException.php index 2ada78d..8d9e154 100644 --- a/Core/Exception/CookieTheftException.php +++ b/Core/Exception/CookieTheftException.php @@ -16,7 +16,15 @@ namespace Symfony\Component\Security\Core\Exception; * detects that a presented cookie has already been used by someone else. * * @author Johannes M. Schmitt <schmittjoh@gmail.com> + * @author Alexander <iam.asm89@gmail.com> */ class CookieTheftException extends AuthenticationException { + /** + * {@inheritDoc} + */ + public function getMessageKey() + { + return 'Cookie has already been used by someone else.'; + } } diff --git a/Core/Exception/CredentialsExpiredException.php b/Core/Exception/CredentialsExpiredException.php index a4d42c8..b9bf2d1 100644 --- a/Core/Exception/CredentialsExpiredException.php +++ b/Core/Exception/CredentialsExpiredException.php @@ -15,7 +15,15 @@ namespace Symfony\Component\Security\Core\Exception; * CredentialsExpiredException is thrown when the user account credentials have expired. * * @author Fabien Potencier <fabien@symfony.com> + * @author Alexander <iam.asm89@gmail.com> */ class CredentialsExpiredException extends AccountStatusException { + /** + * {@inheritDoc} + */ + public function getMessageKey() + { + return 'Credentials have expired.'; + } } diff --git a/Core/Exception/DisabledException.php b/Core/Exception/DisabledException.php index fd26221..5571ab1 100644 --- a/Core/Exception/DisabledException.php +++ b/Core/Exception/DisabledException.php @@ -15,7 +15,15 @@ namespace Symfony\Component\Security\Core\Exception; * DisabledException is thrown when the user account is disabled. * * @author Fabien Potencier <fabien@symfony.com> + * @author Alexander <iam.asm89@gmail.com> */ class DisabledException extends AccountStatusException { + /** + * {@inheritDoc} + */ + public function getMessageKey() + { + return 'Account is disabled.'; + } } diff --git a/Core/Exception/InsufficientAuthenticationException.php b/Core/Exception/InsufficientAuthenticationException.php index bbf5517..74fc2b9 100644 --- a/Core/Exception/InsufficientAuthenticationException.php +++ b/Core/Exception/InsufficientAuthenticationException.php @@ -17,7 +17,15 @@ namespace Symfony\Component\Security\Core\Exception; * This is the case when a user is anonymous and the resource to be displayed has an access role. * * @author Fabien Potencier <fabien@symfony.com> + * @author Alexander <iam.asm89@gmail.com> */ class InsufficientAuthenticationException extends AuthenticationException { + /** + * {@inheritDoc} + */ + public function getMessageKey() + { + return 'Not privileged to request the resource.'; + } } diff --git a/Core/Exception/InvalidCsrfTokenException.php b/Core/Exception/InvalidCsrfTokenException.php index 4181bac..ce0e1f4 100644 --- a/Core/Exception/InvalidCsrfTokenException.php +++ b/Core/Exception/InvalidCsrfTokenException.php @@ -15,7 +15,15 @@ namespace Symfony\Component\Security\Core\Exception; * This exception is thrown when the csrf token is invalid. * * @author Johannes M. Schmitt <schmittjoh@gmail.com> + * @author Alexander <iam.asm89@gmail.com> */ class InvalidCsrfTokenException extends AuthenticationException { + /** + * {@inheritDoc} + */ + public function getMessageKey() + { + return 'Invalid CSRF token.'; + } } diff --git a/Core/Exception/LockedException.php b/Core/Exception/LockedException.php index 6fa0b77..6532f70 100644 --- a/Core/Exception/LockedException.php +++ b/Core/Exception/LockedException.php @@ -15,7 +15,15 @@ namespace Symfony\Component\Security\Core\Exception; * LockedException is thrown if the user account is locked. * * @author Fabien Potencier <fabien@symfony.com> + * @author Alexander <iam.asm89@gmail.com> */ class LockedException extends AccountStatusException { + /** + * {@inheritDoc} + */ + public function getMessageKey() + { + return 'Account is locked.'; + } } diff --git a/Core/Exception/NonceExpiredException.php b/Core/Exception/NonceExpiredException.php index 6a6a781..da6fba8 100644 --- a/Core/Exception/NonceExpiredException.php +++ b/Core/Exception/NonceExpiredException.php @@ -18,7 +18,15 @@ use Symfony\Component\Security\Core\Exception\AuthenticationException; * the digest nonce has expired. * * @author Fabien Potencier <fabien@symfony.com> + * @author Alexander <iam.asm89@gmail.com> */ class NonceExpiredException extends AuthenticationException { + /** + * {@inheritDoc} + */ + public function getMessageKey() + { + return 'Digest nonce has expired.'; + } } diff --git a/Core/Exception/ProviderNotFoundException.php b/Core/Exception/ProviderNotFoundException.php index e11c8aa..ea2b1fd 100644 --- a/Core/Exception/ProviderNotFoundException.php +++ b/Core/Exception/ProviderNotFoundException.php @@ -16,7 +16,15 @@ namespace Symfony\Component\Security\Core\Exception; * supports an authentication Token. * * @author Fabien Potencier <fabien@symfony.com> + * @author Alexander <iam.asm89@gmail.com> */ class ProviderNotFoundException extends AuthenticationException { + /** + * {@inheritDoc} + */ + public function getMessageKey() + { + return 'No authentication provider found to support the authentication token.'; + } } diff --git a/Core/Exception/SessionUnavailableException.php b/Core/Exception/SessionUnavailableException.php index 519164a..4b47b18 100644 --- a/Core/Exception/SessionUnavailableException.php +++ b/Core/Exception/SessionUnavailableException.php @@ -21,7 +21,15 @@ namespace Symfony\Component\Security\Core\Exception; * request. * * @author Johannes M. Schmitt <schmittjoh@gmail.com> + * @author Alexander <iam.asm89@gmail.com> */ class SessionUnavailableException extends AuthenticationException { + /** + * {@inheritDoc} + */ + public function getMessageKey() + { + return 'No session available, it either timed out or cookies are not enabled.'; + } } diff --git a/Core/Exception/TokenNotFoundException.php b/Core/Exception/TokenNotFoundException.php index 593f3ad..fb85abf 100644 --- a/Core/Exception/TokenNotFoundException.php +++ b/Core/Exception/TokenNotFoundException.php @@ -1,5 +1,4 @@ <?php -namespace Symfony\Component\Security\Core\Exception; /* * This file is part of the Symfony package. @@ -10,11 +9,21 @@ namespace Symfony\Component\Security\Core\Exception; * file that was distributed with this source code. */ +namespace Symfony\Component\Security\Core\Exception; + /** * TokenNotFoundException is thrown if a Token cannot be found. * * @author Johannes M. Schmitt <schmittjoh@gmail.com> + * @author Alexander <iam.asm89@gmail.com> */ class TokenNotFoundException extends AuthenticationException { + /** + * {@inheritDoc} + */ + public function getMessageKey() + { + return 'No token could be found.'; + } } diff --git a/Core/Exception/UsernameNotFoundException.php b/Core/Exception/UsernameNotFoundException.php index 38533e7..f656bac 100644 --- a/Core/Exception/UsernameNotFoundException.php +++ b/Core/Exception/UsernameNotFoundException.php @@ -15,7 +15,58 @@ namespace Symfony\Component\Security\Core\Exception; * UsernameNotFoundException is thrown if a User cannot be found by its username. * * @author Fabien Potencier <fabien@symfony.com> + * @author Alexander <iam.asm89@gmail.com> */ class UsernameNotFoundException extends AuthenticationException { + private $username; + + /** + * {@inheritDoc} + */ + public function getMessageKey() + { + return 'Username could not be found.'; + } + + /** + * Get the username. + * + * @return string + */ + public function getUsername() + { + return $this->username; + } + + /** + * Set the username. + * + * @param string $username + */ + public function setUsername($username) + { + $this->username = $username; + } + + /** + * {@inheritDoc} + */ + public function serialize() + { + return serialize(array( + $this->username, + parent::serialize(), + )); + } + + /** + * {@inheritDoc} + */ + public function unserialize($str) + { + list($this->username, $parentData) = unserialize($str); + + parent::unserialize($parentData); + } } diff --git a/Core/Role/RoleHierarchyInterface.php b/Core/Role/RoleHierarchyInterface.php index d873b80..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 */ - function getReachableRoles(array $roles); + public function getReachableRoles(array $roles); } diff --git a/Core/Role/RoleInterface.php b/Core/Role/RoleInterface.php index debda3a..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> */ @@ -31,5 +31,5 @@ interface RoleInterface * * @return string|null A string representation of the role, or null */ - function getRole(); + public function getRole(); } diff --git a/Core/SecurityContext.php b/Core/SecurityContext.php index bc6493b..1ec43e6 100644 --- a/Core/SecurityContext.php +++ b/Core/SecurityContext.php @@ -55,7 +55,7 @@ class SecurityContext implements SecurityContextInterface * * @return Boolean */ - public final function isGranted($attributes, $object = null) + final public function isGranted($attributes, $object = null) { if (null === $this->token) { throw new AuthenticationCredentialsNotFoundException('The security context contains no authentication token. One possible reason may be that there is no firewall configured for this URL.'); diff --git a/Core/SecurityContextInterface.php b/Core/SecurityContextInterface.php index 77c5bf8..78d6477 100644 --- a/Core/SecurityContextInterface.php +++ b/Core/SecurityContextInterface.php @@ -29,14 +29,14 @@ interface SecurityContextInterface * * @return TokenInterface|null A TokenInterface instance or null if no authentication information is available */ - function getToken(); + public function getToken(); /** * Sets the authentication token. * * @param TokenInterface $token */ - function setToken(TokenInterface $token = null); + public function setToken(TokenInterface $token = null); /** * Checks if the attributes are granted against the current authentication token and optionally supplied object. @@ -46,5 +46,5 @@ interface SecurityContextInterface * * @return Boolean */ - function isGranted($attributes, $object = null); + public function isGranted($attributes, $object = null); } diff --git a/Core/User/AdvancedUserInterface.php b/Core/User/AdvancedUserInterface.php index e951c65..5b3a51a 100644 --- a/Core/User/AdvancedUserInterface.php +++ b/Core/User/AdvancedUserInterface.php @@ -47,7 +47,7 @@ interface AdvancedUserInterface extends UserInterface * * @see AccountExpiredException */ - function isAccountNonExpired(); + public function isAccountNonExpired(); /** * Checks whether the user is locked. @@ -59,7 +59,7 @@ interface AdvancedUserInterface extends UserInterface * * @see LockedException */ - function isAccountNonLocked(); + public function isAccountNonLocked(); /** * Checks whether the user's credentials (password) has expired. @@ -71,7 +71,7 @@ interface AdvancedUserInterface extends UserInterface * * @see CredentialsExpiredException */ - function isCredentialsNonExpired(); + public function isCredentialsNonExpired(); /** * Checks whether the user is enabled. @@ -83,5 +83,5 @@ interface AdvancedUserInterface extends UserInterface * * @see DisabledException */ - function isEnabled(); + public function isEnabled(); } diff --git a/Core/User/ChainUserProvider.php b/Core/User/ChainUserProvider.php index 376ba1c..3ff1ea9 100644 --- a/Core/User/ChainUserProvider.php +++ b/Core/User/ChainUserProvider.php @@ -44,7 +44,9 @@ class ChainUserProvider implements UserProviderInterface } } - throw new UsernameNotFoundException(sprintf('There is no user with name "%s".', $username)); + $ex = new UsernameNotFoundException(sprintf('There is no user with name "%s".', $username)); + $ex->setUsername($username); + throw $ex; } /** @@ -66,7 +68,9 @@ class ChainUserProvider implements UserProviderInterface } if ($supportedUserFound) { - throw new UsernameNotFoundException(sprintf('There is no user with name "%s".', $user->getUsername())); + $ex = new UsernameNotFoundException(sprintf('There is no user with name "%s".', $user->getUsername())); + $ex->setUsername($user->getUsername()); + throw $ex; } else { throw new UnsupportedUserException(sprintf('The account "%s" is not supported.', get_class($user))); } diff --git a/Core/User/EquatableInterface.php b/Core/User/EquatableInterface.php index e2bde9e..645b77c 100644 --- a/Core/User/EquatableInterface.php +++ b/Core/User/EquatableInterface.php @@ -33,5 +33,5 @@ interface EquatableInterface * * @return Boolean */ - function isEqualTo(UserInterface $user); + public function isEqualTo(UserInterface $user); } diff --git a/Core/User/InMemoryUserProvider.php b/Core/User/InMemoryUserProvider.php index eae2083..e87f80c 100644 --- a/Core/User/InMemoryUserProvider.php +++ b/Core/User/InMemoryUserProvider.php @@ -50,6 +50,8 @@ class InMemoryUserProvider implements UserProviderInterface * Adds a new User to the provider. * * @param UserInterface $user A UserInterface instance + * + * @throws \LogicException */ public function createUser(UserInterface $user) { @@ -66,7 +68,10 @@ class InMemoryUserProvider implements UserProviderInterface public function loadUserByUsername($username) { if (!isset($this->users[strtolower($username)])) { - throw new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username)); + $ex = new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username)); + $ex->setUsername($username); + + throw $ex; } $user = $this->users[strtolower($username)]; diff --git a/Core/User/User.php b/Core/User/User.php index 6076603..b378e1b 100644 --- a/Core/User/User.php +++ b/Core/User/User.php @@ -22,6 +22,7 @@ final class User implements AdvancedUserInterface { private $username; private $password; + private $enabled; private $accountNonExpired; private $credentialsNonExpired; private $accountNonLocked; diff --git a/Core/User/UserChecker.php b/Core/User/UserChecker.php index 93897a1..8dde3a6 100644 --- a/Core/User/UserChecker.php +++ b/Core/User/UserChecker.php @@ -33,7 +33,9 @@ class UserChecker implements UserCheckerInterface } if (!$user->isCredentialsNonExpired()) { - throw new CredentialsExpiredException('User credentials have expired.', $user); + $ex = new CredentialsExpiredException('User credentials have expired.'); + $ex->setUser($user); + throw $ex; } } @@ -47,15 +49,21 @@ class UserChecker implements UserCheckerInterface } if (!$user->isAccountNonLocked()) { - throw new LockedException('User account is locked.', $user); + $ex = new LockedException('User account is locked.'); + $ex->setUser($user); + throw $ex; } if (!$user->isEnabled()) { - throw new DisabledException('User account is disabled.', $user); + $ex = new DisabledException('User account is disabled.'); + $ex->setUser($user); + throw $ex; } if (!$user->isAccountNonExpired()) { - throw new AccountExpiredException('User account has expired.', $user); + $ex = new AccountExpiredException('User account has expired.'); + $ex->setUser($user); + throw $ex; } } } diff --git a/Core/User/UserCheckerInterface.php b/Core/User/UserCheckerInterface.php index 61f0f6e..3dd8d51 100644 --- a/Core/User/UserCheckerInterface.php +++ b/Core/User/UserCheckerInterface.php @@ -25,12 +25,12 @@ interface UserCheckerInterface * * @param UserInterface $user a UserInterface instance */ - function checkPreAuth(UserInterface $user); + public function checkPreAuth(UserInterface $user); /** * Checks the user account after authentication. * * @param UserInterface $user a UserInterface instance */ - function checkPostAuth(UserInterface $user); + public function checkPostAuth(UserInterface $user); } diff --git a/Core/User/UserInterface.php b/Core/User/UserInterface.php index ce3b3a8..ed96ca9 100644 --- a/Core/User/UserInterface.php +++ b/Core/User/UserInterface.php @@ -47,7 +47,7 @@ interface UserInterface * * @return Role[] The user roles */ - function getRoles(); + public function getRoles(); /** * Returns the password used to authenticate the user. @@ -57,7 +57,7 @@ interface UserInterface * * @return string The password */ - function getPassword(); + public function getPassword(); /** * Returns the salt that was originally used to encode the password. @@ -66,14 +66,14 @@ interface UserInterface * * @return string The salt */ - function getSalt(); + public function getSalt(); /** * Returns the username used to authenticate the user. * * @return string The username */ - function getUsername(); + public function getUsername(); /** * Removes sensitive data from the user. @@ -83,5 +83,5 @@ interface UserInterface * * @return void */ - function eraseCredentials(); + public function eraseCredentials(); } diff --git a/Core/User/UserProviderInterface.php b/Core/User/UserProviderInterface.php index dbd7924..6669c43 100644 --- a/Core/User/UserProviderInterface.php +++ b/Core/User/UserProviderInterface.php @@ -48,7 +48,7 @@ interface UserProviderInterface * @throws UsernameNotFoundException if the user is not found * */ - function loadUserByUsername($username); + public function loadUserByUsername($username); /** * Refreshes the user for the account interface. @@ -63,7 +63,7 @@ interface UserProviderInterface * * @throws UnsupportedUserException if the account is not supported */ - function refreshUser(UserInterface $user); + public function refreshUser(UserInterface $user); /** * Whether this provider supports the given user class @@ -72,5 +72,5 @@ interface UserProviderInterface * * @return Boolean */ - function supportsClass($class); + public function supportsClass($class); } 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/SecureRandom.php b/Core/Util/SecureRandom.php new file mode 100644 index 0000000..841b9af --- /dev/null +++ b/Core/Util/SecureRandom.php @@ -0,0 +1,114 @@ +<?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\Core\Util; + +use Psr\Log\LoggerInterface; + +/** + * A secure random number generator implementation. + * + * @author Fabien Potencier <fabien@symfony.com> + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +final class SecureRandom implements SecureRandomInterface +{ + private $logger; + private $useOpenSsl; + private $seed; + private $seedUpdated; + private $seedLastUpdatedAt; + private $seedFile; + + /** + * Constructor. + * + * Be aware that a guessable seed will severely compromise the PRNG + * algorithm that is employed. + * + * @param string $seedFile + * @param LoggerInterface $logger + */ + public function __construct($seedFile = null, LoggerInterface $logger = null) + { + $this->seedFile = $seedFile; + $this->logger = $logger; + + // determine whether to use OpenSSL + if (defined('PHP_WINDOWS_VERSION_BUILD') && version_compare(PHP_VERSION, '5.3.4', '<')) { + $this->useOpenSsl = false; + } elseif (!function_exists('openssl_random_pseudo_bytes')) { + if (null !== $this->logger) { + $this->logger->notice('It is recommended that you enable the "openssl" extension for random number generation.'); + } + $this->useOpenSsl = false; + } else { + $this->useOpenSsl = true; + } + } + + /** + * {@inheritdoc} + */ + public function nextBytes($nbBytes) + { + // try OpenSSL + if ($this->useOpenSsl) { + $bytes = openssl_random_pseudo_bytes($nbBytes, $strong); + + if (false !== $bytes && true === $strong) { + return $bytes; + } + + if (null !== $this->logger) { + $this->logger->info('OpenSSL did not produce a secure random number.'); + } + } + + // initialize seed + if (null === $this->seed) { + if (null === $this->seedFile) { + throw new \RuntimeException('You need to specify a file path to store the seed.'); + } + + if (is_file($this->seedFile)) { + list($this->seed, $this->seedLastUpdatedAt) = $this->readSeed(); + } else { + $this->seed = uniqid(mt_rand(), true); + $this->updateSeed(); + } + } + + $bytes = ''; + while (strlen($bytes) < $nbBytes) { + static $incr = 1; + $bytes .= hash('sha512', $incr++.$this->seed.uniqid(mt_rand(), true).$nbBytes, true); + $this->seed = base64_encode(hash('sha512', $this->seed.$bytes.$nbBytes, true)); + $this->updateSeed(); + } + + return substr($bytes, 0, $nbBytes); + } + + private function readSeed() + { + return json_decode(file_get_contents($this->seedFile)); + } + + private function updateSeed() + { + if (!$this->seedUpdated && $this->seedLastUpdatedAt < time() - mt_rand(1, 10)) { + file_put_contents($this->seedFile, json_encode(array($this->seed, microtime(true)))); + } + + $this->seedUpdated = true; + } +} diff --git a/Core/Util/SecureRandomInterface.php b/Core/Util/SecureRandomInterface.php new file mode 100644 index 0000000..2c35a72 --- /dev/null +++ b/Core/Util/SecureRandomInterface.php @@ -0,0 +1,29 @@ +<?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\Core\Util; + +/** + * Interface that needs to be implemented by all secure random number generators. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +interface SecureRandomInterface +{ + /** + * Generates the specified number of secure random bytes. + * + * @param integer $nbBytes + * + * @return string + */ + public function nextBytes($nbBytes); +} diff --git a/Core/Util/StringUtils.php b/Core/Util/StringUtils.php new file mode 100644 index 0000000..2e8925d --- /dev/null +++ b/Core/Util/StringUtils.php @@ -0,0 +1,60 @@ +<?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\Core\Util; + +/** + * String utility functions. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class StringUtils +{ + /** + * This class should not be instantiated + */ + private function __construct() {} + + /** + * Compares two strings. + * + * This method implements a constant-time algorithm to compare strings. + * + * @param string $knownString The string of known length to compare against + * @param string $userInput The string that the user can control + * + * @return Boolean true if the two strings are the same, false otherwise + */ + public static function equals($knownString, $userInput) + { + // Prevent issues if string length is 0 + $knownString .= chr(0); + $userInput .= chr(0); + + $knownLen = strlen($knownString); + $userLen = strlen($userInput); + + // Set the result to the difference between the lengths + $result = $knownLen - $userLen; + + // Note that we ALWAYS iterate over the user-supplied length + // This is to prevent leaking length information + for ($i = 0; $i < $userLen; $i++) { + // Using % here is a trick to prevent notices + // It's safe, since if the lengths are different + // $result is already non-0 + $result |= (ord($knownString[$i % $knownLen]) ^ ord($userInput[$i])); + } + + // They are only identical strings if $result is exactly 0... + return 0 === $result; + } +} diff --git a/Core/Validator/Constraint/UserPassword.php b/Core/Validator/Constraints/UserPassword.php index ef6e1ec..ed29b0c 100644 --- a/Core/Validator/Constraint/UserPassword.php +++ b/Core/Validator/Constraints/UserPassword.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Security\Core\Validator\Constraint; +namespace Symfony\Component\Security\Core\Validator\Constraints; use Symfony\Component\Validator\Constraint; @@ -18,10 +18,11 @@ use Symfony\Component\Validator\Constraint; */ class UserPassword extends Constraint { - public $message = 'This value should be the user current password'; + public $message = 'This value should be the user current password.'; + public $service = 'security.validator.user_password'; public function validatedBy() { - return 'security.validator.user_password'; + return $this->service; } } diff --git a/Core/Validator/Constraint/UserPasswordValidator.php b/Core/Validator/Constraints/UserPasswordValidator.php index a54906b..a4e0f90 100644 --- a/Core/Validator/Constraint/UserPasswordValidator.php +++ b/Core/Validator/Constraints/UserPasswordValidator.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Security\Core\Validator\Constraint; +namespace Symfony\Component\Security\Core\Validator\Constraints; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\SecurityContextInterface; @@ -34,7 +34,7 @@ class UserPasswordValidator extends ConstraintValidator $user = $this->securityContext->getToken()->getUser(); if (!$user instanceof UserInterface) { - throw new ConstraintDefinitionException('The User must extend UserInterface'); + throw new ConstraintDefinitionException('The User object must implement the UserInterface interface.'); } $encoder = $this->encoderFactory->getEncoder($user); diff --git a/Http/AccessMapInterface.php b/Http/AccessMapInterface.php index dbd7282..7d15fee 100644 --- a/Http/AccessMapInterface.php +++ b/Http/AccessMapInterface.php @@ -29,5 +29,5 @@ interface AccessMapInterface * * @return array A tuple of security attributes and the required channel */ - function getPatterns(Request $request); + public function getPatterns(Request $request); } diff --git a/Http/Authentication/AuthenticationFailureHandlerInterface.php b/Http/Authentication/AuthenticationFailureHandlerInterface.php index 9cd7496..8dbd29a 100644 --- a/Http/Authentication/AuthenticationFailureHandlerInterface.php +++ b/Http/Authentication/AuthenticationFailureHandlerInterface.php @@ -33,7 +33,7 @@ interface AuthenticationFailureHandlerInterface * @param Request $request * @param AuthenticationException $exception * - * @return Response|null the response to return + * @return Response The response to return, never null */ - function onAuthenticationFailure(Request $request, AuthenticationException $exception); + public function onAuthenticationFailure(Request $request, AuthenticationException $exception); } diff --git a/Http/Authentication/AuthenticationSuccessHandlerInterface.php b/Http/Authentication/AuthenticationSuccessHandlerInterface.php index 8917f3e..5c08e73 100644 --- a/Http/Authentication/AuthenticationSuccessHandlerInterface.php +++ b/Http/Authentication/AuthenticationSuccessHandlerInterface.php @@ -33,7 +33,7 @@ interface AuthenticationSuccessHandlerInterface * @param Request $request * @param TokenInterface $token * - * @return Response|null the response to return + * @return Response never null */ - function onAuthenticationSuccess(Request $request, TokenInterface $token); + public function onAuthenticationSuccess(Request $request, TokenInterface $token); } diff --git a/Http/Authentication/DefaultAuthenticationFailureHandler.php b/Http/Authentication/DefaultAuthenticationFailureHandler.php new file mode 100644 index 0000000..64f84f0 --- /dev/null +++ b/Http/Authentication/DefaultAuthenticationFailureHandler.php @@ -0,0 +1,92 @@ +<?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\Http\Authentication; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Psr\Log\LoggerInterface; +use Symfony\Component\Security\Core\Exception\AuthenticationException; +use Symfony\Component\Security\Core\SecurityContextInterface; +use Symfony\Component\Security\Http\HttpUtils; + +/** + * Class with the default authentication failure handling logic. + * + * Can be optionally be extended from by the developer to alter the behaviour + * while keeping the default behaviour. + * + * @author Fabien Potencier <fabien@symfony.com> + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + * @author Alexander <iam.asm89@gmail.com> + */ +class DefaultAuthenticationFailureHandler implements AuthenticationFailureHandlerInterface +{ + protected $httpKernel; + protected $httpUtils; + protected $logger; + protected $options; + + /** + * Constructor. + * + * @param HttpKernelInterface $httpKernel + * @param HttpUtils $httpUtils + * @param array $options Options for processing a failed authentication attempt. + * @param LoggerInterface $logger Optional logger + */ + public function __construct(HttpKernelInterface $httpKernel, HttpUtils $httpUtils, array $options, LoggerInterface $logger = null) + { + $this->httpKernel = $httpKernel; + $this->httpUtils = $httpUtils; + $this->logger = $logger; + + $this->options = array_merge(array( + 'failure_path' => null, + 'failure_forward' => false, + 'login_path' => '/login', + 'failure_path_parameter' => '_failure_path' + ), $options); + } + + /** + * {@inheritDoc} + */ + public function onAuthenticationFailure(Request $request, AuthenticationException $exception) + { + if ($failureUrl = $request->get($this->options['failure_path_parameter'], null, true)) { + $this->options['failure_path'] = $failureUrl; + } + + if (null === $this->options['failure_path']) { + $this->options['failure_path'] = $this->options['login_path']; + } + + if ($this->options['failure_forward']) { + if (null !== $this->logger) { + $this->logger->debug(sprintf('Forwarding to %s', $this->options['failure_path'])); + } + + $subRequest = $this->httpUtils->createRequest($request, $this->options['failure_path']); + $subRequest->attributes->set(SecurityContextInterface::AUTHENTICATION_ERROR, $exception); + + return $this->httpKernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST); + } + + if (null !== $this->logger) { + $this->logger->debug(sprintf('Redirecting to %s', $this->options['failure_path'])); + } + + $request->getSession()->set(SecurityContextInterface::AUTHENTICATION_ERROR, $exception); + + return $this->httpUtils->createRedirectResponse($request, $this->options['failure_path']); + } +} diff --git a/Http/Authentication/DefaultAuthenticationSuccessHandler.php b/Http/Authentication/DefaultAuthenticationSuccessHandler.php new file mode 100644 index 0000000..dd7a7d5 --- /dev/null +++ b/Http/Authentication/DefaultAuthenticationSuccessHandler.php @@ -0,0 +1,110 @@ +<?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\Http\Authentication; + +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Http\HttpUtils; + +/** + * Class with the default authentication success handling logic. + * + * Can be optionally be extended from by the developer to alter the behaviour + * while keeping the default behaviour. + * + * @author Fabien Potencier <fabien@symfony.com> + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + * @author Alexander <iam.asm89@gmail.com> + */ +class DefaultAuthenticationSuccessHandler implements AuthenticationSuccessHandlerInterface +{ + protected $httpUtils; + protected $options; + protected $providerKey; + + /** + * Constructor. + * + * @param HttpUtils $httpUtils + * @param array $options Options for processing a successful authentication attempt. + */ + public function __construct(HttpUtils $httpUtils, array $options) + { + $this->httpUtils = $httpUtils; + + $this->options = array_merge(array( + 'always_use_default_target_path' => false, + 'default_target_path' => '/', + 'login_path' => '/login', + 'target_path_parameter' => '_target_path', + 'use_referer' => false, + ), $options); + } + + /** + * {@inheritDoc} + */ + public function onAuthenticationSuccess(Request $request, TokenInterface $token) + { + return $this->httpUtils->createRedirectResponse($request, $this->determineTargetUrl($request)); + } + + /** + * Get the provider key. + * + * @return string + */ + public function getProviderKey() + { + return $this->providerKey; + } + + /** + * Set the provider key. + * + * @param string $providerKey + */ + public function setProviderKey($providerKey) + { + $this->providerKey = $providerKey; + } + + /** + * Builds the target URL according to the defined options. + * + * @param Request $request + * + * @return string + */ + protected function determineTargetUrl(Request $request) + { + if ($this->options['always_use_default_target_path']) { + return $this->options['default_target_path']; + } + + if ($targetUrl = $request->get($this->options['target_path_parameter'], null, true)) { + return $targetUrl; + } + + if (null !== $this->providerKey && $targetUrl = $request->getSession()->get('_security.'.$this->providerKey.'.target_path')) { + $request->getSession()->remove('_security.'.$this->providerKey.'.target_path'); + + return $targetUrl; + } + + if ($this->options['use_referer'] && ($targetUrl = $request->headers->get('Referer')) && $targetUrl !== $this->httpUtils->generateUri($request, $this->options['login_path'])) { + return $targetUrl; + } + + return $this->options['default_target_path']; + } +} diff --git a/Http/Authorization/AccessDeniedHandlerInterface.php b/Http/Authorization/AccessDeniedHandlerInterface.php index 8670cbb..a10a5d0 100644 --- a/Http/Authorization/AccessDeniedHandlerInterface.php +++ b/Http/Authorization/AccessDeniedHandlerInterface.php @@ -30,5 +30,5 @@ interface AccessDeniedHandlerInterface * * @return Response may return null */ - function handle(Request $request, AccessDeniedException $accessDeniedException); + public function handle(Request $request, AccessDeniedException $accessDeniedException); } diff --git a/Http/EntryPoint/AuthenticationEntryPointInterface.php b/Http/EntryPoint/AuthenticationEntryPointInterface.php index 9fc3501..d190fc7 100644 --- a/Http/EntryPoint/AuthenticationEntryPointInterface.php +++ b/Http/EntryPoint/AuthenticationEntryPointInterface.php @@ -30,5 +30,5 @@ interface AuthenticationEntryPointInterface * * @return Response */ - function start(Request $request, AuthenticationException $authException = null); + public function start(Request $request, AuthenticationException $authException = null); } 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..1131b58 100644 --- a/Http/EntryPoint/DigestAuthenticationEntryPoint.php +++ b/Http/EntryPoint/DigestAuthenticationEntryPoint.php @@ -16,7 +16,7 @@ use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface use Symfony\Component\Security\Core\Exception\NonceExpiredException; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Log\LoggerInterface; +use Psr\Log\LoggerInterface; /** * DigestAuthenticationEntryPoint starts an HTTP Digest authentication. @@ -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/Event/InteractiveLoginEvent.php b/Http/Event/InteractiveLoginEvent.php index f242501..2225d92 100644 --- a/Http/Event/InteractiveLoginEvent.php +++ b/Http/Event/InteractiveLoginEvent.php @@ -21,17 +21,33 @@ class InteractiveLoginEvent extends Event private $authenticationToken; + /** + * Constructor. + * + * @param Request $request A Request instance + * @param TokenInterface $authenticationToken A TokenInterface instance + */ public function __construct(Request $request, TokenInterface $authenticationToken) { $this->request = $request; $this->authenticationToken = $authenticationToken; } + /** + * Gets the request. + * + * @return Request A Request instance + */ public function getRequest() { return $this->request; } + /** + * Gets the authentication token. + * + * @return TokenInterface A TokenInterface instance + */ public function getAuthenticationToken() { return $this->authenticationToken; diff --git a/Http/Firewall.php b/Http/Firewall.php index 91eb6a9..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; @@ -33,7 +35,7 @@ class Firewall /** * Constructor. * - * @param FirewallMap $map A FirewallMap instance + * @param FirewallMapInterface $map A FirewallMapInterface instance * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance */ public function __construct(FirewallMapInterface $map, EventDispatcherInterface $dispatcher) @@ -68,4 +70,9 @@ class Firewall } } } + + public static function getSubscribedEvents() + { + return array(KernelEvents::REQUEST => array('onKernelRequest', 8)); + } } diff --git a/Http/Firewall/AbstractAuthenticationListener.php b/Http/Firewall/AbstractAuthenticationListener.php index a5924ff..562ba10 100644 --- a/Http/Firewall/AbstractAuthenticationListener.php +++ b/Http/Firewall/AbstractAuthenticationListener.php @@ -19,8 +19,7 @@ use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\SessionUnavailableException; -use Symfony\Component\HttpKernel\Log\LoggerInterface; -use Symfony\Component\HttpKernel\HttpKernelInterface; +use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -70,14 +69,16 @@ abstract class AbstractAuthenticationListener implements ListenerInterface * @param SessionAuthenticationStrategyInterface $sessionStrategy * @param HttpUtils $httpUtils An HttpUtilsInterface instance * @param string $providerKey + * @param AuthenticationSuccessHandlerInterface $successHandler + * @param AuthenticationFailureHandlerInterface $failureHandler * @param array $options An array of options for the processing of a * successful, or failed authentication attempt - * @param AuthenticationSuccessHandlerInterface $successHandler - * @param AuthenticationFailureHandlerInterface $failureHandler - * @param LoggerInterface $logger A LoggerInterface instance - * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance + * @param LoggerInterface $logger A LoggerInterface instance + * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance + * + * @throws \InvalidArgumentException */ - public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, array $options = array(), AuthenticationSuccessHandlerInterface $successHandler = null, AuthenticationFailureHandlerInterface $failureHandler = null, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null) + public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = array(), LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null) { if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); @@ -119,8 +120,11 @@ abstract class AbstractAuthenticationListener implements ListenerInterface * Handles form based authentication. * * @param GetResponseEvent $event A GetResponseEvent instance + * + * @throws \RuntimeException + * @throws SessionUnavailableException */ - public final function handle(GetResponseEvent $event) + final public function handle(GetResponseEvent $event) { $request = $event->getRequest(); @@ -178,7 +182,7 @@ abstract class AbstractAuthenticationListener implements ListenerInterface * * @param Request $request A Request instance * - * @return TokenInterface The authenticated token, or null if full authentication is not possible + * @return TokenInterface|Response|null The authenticated token, null if full authentication is not possible, or a Response * * @throws AuthenticationException if the authentication fails */ @@ -192,34 +196,13 @@ abstract class AbstractAuthenticationListener implements ListenerInterface $this->securityContext->setToken(null); - if (null !== $this->failureHandler) { - if (null !== $response = $this->failureHandler->onAuthenticationFailure($request, $failed)) { - return $response; - } - } - - if (null === $this->options['failure_path']) { - $this->options['failure_path'] = $this->options['login_path']; - } - - if ($this->options['failure_forward']) { - if (null !== $this->logger) { - $this->logger->debug(sprintf('Forwarding to %s', $this->options['failure_path'])); - } - - $subRequest = $this->httpUtils->createRequest($request, $this->options['failure_path']); - $subRequest->attributes->set(SecurityContextInterface::AUTHENTICATION_ERROR, $failed); + $response = $this->failureHandler->onAuthenticationFailure($request, $failed); - return $event->getKernel()->handle($subRequest, HttpKernelInterface::SUB_REQUEST); + if (!$response instanceof Response) { + throw new \RuntimeException('Authentication Failure Handler did not return a Response.'); } - if (null !== $this->logger) { - $this->logger->debug(sprintf('Redirecting to %s', $this->options['failure_path'])); - } - - $request->getSession()->set(SecurityContextInterface::AUTHENTICATION_ERROR, $failed); - - return $this->httpUtils->createRedirectResponse($request, $this->options['failure_path']); + return $response; } private function onSuccess(GetResponseEvent $event, Request $request, TokenInterface $token) @@ -239,12 +222,10 @@ abstract class AbstractAuthenticationListener implements ListenerInterface $this->dispatcher->dispatch(SecurityEvents::INTERACTIVE_LOGIN, $loginEvent); } - $response = null; - if (null !== $this->successHandler) { - $response = $this->successHandler->onAuthenticationSuccess($request, $token); - } - if (null === $response) { - $response = $this->httpUtils->createRedirectResponse($request, $this->determineTargetUrl($request)); + $response = $this->successHandler->onAuthenticationSuccess($request, $token); + + if (!$response instanceof Response) { + throw new \RuntimeException('Authentication Success Handler did not return a Response.'); } if (null !== $this->rememberMeServices) { @@ -253,35 +234,4 @@ abstract class AbstractAuthenticationListener implements ListenerInterface return $response; } - - /** - * Builds the target URL according to the defined options. - * - * @param Request $request - * - * @return string - */ - private function determineTargetUrl(Request $request) - { - if ($this->options['always_use_default_target_path']) { - return $this->options['default_target_path']; - } - - if ($targetUrl = $request->get($this->options['target_path_parameter'], null, true)) { - return $targetUrl; - } - - $session = $request->getSession(); - if ($targetUrl = $session->get('_security.' . $this->providerKey . '.target_path')) { - $session->remove('_security.' . $this->providerKey . '.target_path'); - - return $targetUrl; - } - - if ($this->options['use_referer'] && ($targetUrl = $request->headers->get('Referer')) && $targetUrl !== $request->getUriForPath($this->options['login_path'])) { - return $targetUrl; - } - - return $this->options['default_target_path']; - } } diff --git a/Http/Firewall/AbstractPreAuthenticatedListener.php b/Http/Firewall/AbstractPreAuthenticatedListener.php index 66d0ea1..d7e46cf 100644 --- a/Http/Firewall/AbstractPreAuthenticatedListener.php +++ b/Http/Firewall/AbstractPreAuthenticatedListener.php @@ -18,7 +18,7 @@ use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; use Symfony\Component\Security\Http\SecurityEvents; use Symfony\Component\HttpKernel\Event\GetResponseEvent; -use Symfony\Component\HttpKernel\Log\LoggerInterface; +use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -51,7 +51,7 @@ abstract class AbstractPreAuthenticatedListener implements ListenerInterface * * @param GetResponseEvent $event A GetResponseEvent instance */ - public final function handle(GetResponseEvent $event) + final public function handle(GetResponseEvent $event) { $request = $event->getRequest(); diff --git a/Http/Firewall/AccessListener.php b/Http/Firewall/AccessListener.php index 3e2d3a5..c3894ef 100644 --- a/Http/Firewall/AccessListener.php +++ b/Http/Firewall/AccessListener.php @@ -15,7 +15,7 @@ use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; use Symfony\Component\Security\Http\AccessMapInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; -use Symfony\Component\HttpKernel\Log\LoggerInterface; +use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException; use Symfony\Component\Security\Core\Exception\AccessDeniedException; @@ -46,6 +46,9 @@ class AccessListener implements ListenerInterface * Handles access authorization. * * @param GetResponseEvent $event A GetResponseEvent instance + * + * @throws AccessDeniedException + * @throws AuthenticationCredentialsNotFoundException */ public function handle(GetResponseEvent $event) { diff --git a/Http/Firewall/AnonymousAuthenticationListener.php b/Http/Firewall/AnonymousAuthenticationListener.php index d00865d..af2213b 100644 --- a/Http/Firewall/AnonymousAuthenticationListener.php +++ b/Http/Firewall/AnonymousAuthenticationListener.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Core\SecurityContextInterface; -use Symfony\Component\HttpKernel\Log\LoggerInterface; +use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; diff --git a/Http/Firewall/BasicAuthenticationListener.php b/Http/Firewall/BasicAuthenticationListener.php index e331179..5b1c8b3 100644 --- a/Http/Firewall/BasicAuthenticationListener.php +++ b/Http/Firewall/BasicAuthenticationListener.php @@ -14,7 +14,7 @@ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; -use Symfony\Component\HttpKernel\Log\LoggerInterface; +use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Exception\AuthenticationException; diff --git a/Http/Firewall/ChannelListener.php b/Http/Firewall/ChannelListener.php index 9b0f8c6..9e4a6ee 100644 --- a/Http/Firewall/ChannelListener.php +++ b/Http/Firewall/ChannelListener.php @@ -13,7 +13,7 @@ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Http\AccessMapInterface; use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; -use Symfony\Component\HttpKernel\Log\LoggerInterface; +use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; /** diff --git a/Http/Firewall/ContextListener.php b/Http/Firewall/ContextListener.php index bb1e308..8c71876 100644 --- a/Http/Firewall/ContextListener.php +++ b/Http/Firewall/ContextListener.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\HttpKernel\Log\LoggerInterface; +use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; @@ -70,24 +70,31 @@ class ContextListener implements ListenerInterface } $request = $event->getRequest(); - $session = $request->hasPreviousSession() ? $request->getSession() : null; if (null === $session || null === $token = $session->get('_security_'.$this->contextKey)) { $this->context->setToken(null); - } else { - if (null !== $this->logger) { - $this->logger->debug('Read SecurityContext from the session'); - } - $token = unserialize($token); + return; + } + + $token = unserialize($token); + + if (null !== $this->logger) { + $this->logger->debug('Read SecurityContext from the session'); + } - if (null !== $token) { - $token = $this->refreshUser($token); + if ($token instanceof TokenInterface) { + $token = $this->refreshUser($token); + } elseif (null !== $token) { + if (null !== $this->logger) { + $this->logger->warning(sprintf('Session includes a "%s" where a security token is expected', is_object($token) ? get_class($token) : gettype($token))); } - $this->context->setToken($token); + $token = null; } + + $this->context->setToken($token); } /** @@ -109,12 +116,17 @@ class ContextListener implements ListenerInterface $this->logger->debug('Write SecurityContext in the session'); } - if (null === $session = $event->getRequest()->getSession()) { + $request = $event->getRequest(); + $session = $request->getSession(); + + if (null === $session) { return; } if ((null === $token = $this->context->getToken()) || ($token instanceof AnonymousToken)) { - $session->remove('_security_'.$this->contextKey); + if ($request->hasPreviousSession()) { + $session->remove('_security_'.$this->contextKey); + } } else { $session->set('_security_'.$this->contextKey, serialize($token)); } @@ -126,6 +138,8 @@ class ContextListener implements ListenerInterface * @param TokenInterface $token * * @return TokenInterface|null + * + * @throws \RuntimeException */ private function refreshUser(TokenInterface $token) { @@ -151,7 +165,7 @@ class ContextListener implements ListenerInterface // let's try the next user provider } catch (UsernameNotFoundException $notFound) { if (null !== $this->logger) { - $this->logger->warn(sprintf('Username "%s" could not be found.', $user->getUsername())); + $this->logger->warning(sprintf('Username "%s" could not be found.', $user->getUsername())); } return null; diff --git a/Http/Firewall/DigestAuthenticationListener.php b/Http/Firewall/DigestAuthenticationListener.php index 5c529da..7ab3dcf 100644 --- a/Http/Firewall/DigestAuthenticationListener.php +++ b/Http/Firewall/DigestAuthenticationListener.php @@ -14,7 +14,7 @@ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Http\EntryPoint\DigestAuthenticationEntryPoint; -use Symfony\Component\HttpKernel\Log\LoggerInterface; +use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Exception\BadCredentialsException; @@ -54,6 +54,8 @@ class DigestAuthenticationListener implements ListenerInterface * Handles digest authentication. * * @param GetResponseEvent $event A GetResponseEvent instance + * + * @throws AuthenticationServiceException */ public function handle(GetResponseEvent $event) { @@ -141,11 +143,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 +159,7 @@ class DigestData public function getUsername() { - return $this->elements['username']; + return strtr($this->elements['username'], array("\\\"" => "\"", "\\\\" => "\\")); } public function validateAndDecode($entryPointKey, $expectedRealm) @@ -188,7 +191,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/Firewall/ExceptionListener.php b/Http/Firewall/ExceptionListener.php index 9a53827..0f81d1b 100644 --- a/Http/Firewall/ExceptionListener.php +++ b/Http/Firewall/ExceptionListener.php @@ -23,7 +23,7 @@ use Symfony\Component\Security\Core\Exception\InsufficientAuthenticationExceptio use Symfony\Component\Security\Core\Exception\LogoutException; use Symfony\Component\Security\Http\HttpUtils; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Log\LoggerInterface; +use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; @@ -97,6 +97,8 @@ class ExceptionListener return; } } elseif ($exception instanceof AccessDeniedException) { + $event->setException(new AccessDeniedHttpException($exception->getMessage(), $exception)); + $token = $this->context->getToken(); if (!$this->authenticationTrustResolver->isFullFledged($token)) { if (null !== $this->logger) { @@ -104,7 +106,9 @@ class ExceptionListener } try { - $response = $this->startAuthentication($request, new InsufficientAuthenticationException('Full authentication is required to access this resource.', $token, 0, $exception)); + $insufficientAuthenticationException = new InsufficientAuthenticationException('Full authentication is required to access this resource.', 0, $exception); + $insufficientAuthenticationException->setToken($token); + $response = $this->startAuthentication($request, $insufficientAuthenticationException); } catch (\Exception $e) { $event->setException($e); @@ -127,15 +131,12 @@ class ExceptionListener $subRequest->attributes->set(SecurityContextInterface::ACCESS_DENIED_ERROR, $exception); $response = $event->getKernel()->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true); - $response->setStatusCode(403); } else { - $event->setException(new AccessDeniedHttpException($exception->getMessage(), $exception)); - return; } } catch (\Exception $e) { if (null !== $this->logger) { - $this->logger->err(sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $e->getMessage())); + $this->logger->error(sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $e->getMessage())); } $event->setException(new \RuntimeException('Exception thrown when handling an exception.', 0, $e)); @@ -148,8 +149,6 @@ class ExceptionListener $this->logger->info(sprintf('Logout exception occurred; wrapping with AccessDeniedHttpException (%s)', $exception->getMessage())); } - $event->setException(new AccessDeniedHttpException($exception->getMessage(), $exception)); - return; } else { return; diff --git a/Http/Firewall/ListenerInterface.php b/Http/Firewall/ListenerInterface.php index ccde86e..b670474 100644 --- a/Http/Firewall/ListenerInterface.php +++ b/Http/Firewall/ListenerInterface.php @@ -25,5 +25,5 @@ interface ListenerInterface * * @param GetResponseEvent $event */ - function handle(GetResponseEvent $event); + public function handle(GetResponseEvent $event); } diff --git a/Http/Firewall/LogoutListener.php b/Http/Firewall/LogoutListener.php index d145fa1..ca2f439 100644 --- a/Http/Firewall/LogoutListener.php +++ b/Http/Firewall/LogoutListener.php @@ -40,11 +40,11 @@ class LogoutListener implements ListenerInterface * * @param SecurityContextInterface $securityContext * @param HttpUtils $httpUtils An HttpUtilsInterface instance - * @param array $options An array of options to process a logout attempt * @param LogoutSuccessHandlerInterface $successHandler A LogoutSuccessHandlerInterface instance + * @param array $options An array of options to process a logout attempt * @param CsrfProviderInterface $csrfProvider A CsrfProviderInterface instance */ - public function __construct(SecurityContextInterface $securityContext, HttpUtils $httpUtils, array $options = array(), LogoutSuccessHandlerInterface $successHandler = null, CsrfProviderInterface $csrfProvider = null) + public function __construct(SecurityContextInterface $securityContext, HttpUtils $httpUtils, LogoutSuccessHandlerInterface $successHandler, array $options = array(), CsrfProviderInterface $csrfProvider = null) { $this->securityContext = $securityContext; $this->httpUtils = $httpUtils; @@ -52,7 +52,6 @@ class LogoutListener implements ListenerInterface 'csrf_parameter' => '_csrf_token', 'intention' => 'logout', 'logout_path' => '/logout', - 'target_url' => '/', ), $options); $this->successHandler = $successHandler; $this->csrfProvider = $csrfProvider; @@ -76,8 +75,10 @@ class LogoutListener implements ListenerInterface * validate the request. * * @param GetResponseEvent $event A GetResponseEvent instance + * * @throws InvalidCsrfTokenException if the CSRF token is invalid - * @throws RuntimeException if the LogoutSuccessHandlerInterface instance does not return a response + * @throws \RuntimeException if the LogoutSuccessHandlerInterface instance does not return a response + * @throws LogoutException */ public function handle(GetResponseEvent $event) { @@ -95,14 +96,9 @@ class LogoutListener implements ListenerInterface } } - if (null !== $this->successHandler) { - $response = $this->successHandler->onLogoutSuccess($request); - - if (!$response instanceof Response) { - throw new \RuntimeException('Logout Success Handler did not return a Response.'); - } - } else { - $response = $this->httpUtils->createRedirectResponse($request, $this->options['target_url']); + $response = $this->successHandler->onLogoutSuccess($request); + if (!$response instanceof Response) { + throw new \RuntimeException('Logout Success Handler did not return a Response.'); } // handle multiple logout attempts gracefully diff --git a/Http/Firewall/RememberMeListener.php b/Http/Firewall/RememberMeListener.php index 3614f79..5a856e2 100644 --- a/Http/Firewall/RememberMeListener.php +++ b/Http/Firewall/RememberMeListener.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Security\Http\Firewall; -use Symfony\Component\HttpKernel\Log\LoggerInterface; +use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; @@ -82,7 +82,7 @@ class RememberMeListener implements ListenerInterface } } catch (AuthenticationException $failed) { if (null !== $this->logger) { - $this->logger->warn( + $this->logger->warning( 'SecurityContext not populated with remember-me token as the' .' AuthenticationManager rejected the AuthenticationToken returned' .' by the RememberMeServices: '.$failed->getMessage() diff --git a/Http/Firewall/SwitchUserListener.php b/Http/Firewall/SwitchUserListener.php index 7f0aa78..bad6b2b 100644 --- a/Http/Firewall/SwitchUserListener.php +++ b/Http/Firewall/SwitchUserListener.php @@ -16,7 +16,7 @@ use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserCheckerInterface; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; -use Symfony\Component\HttpKernel\Log\LoggerInterface; +use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\HttpFoundation\RedirectResponse; @@ -71,6 +71,8 @@ class SwitchUserListener implements ListenerInterface * Handles digest authentication. * * @param GetResponseEvent $event A GetResponseEvent instance + * + * @throws \LogicException */ public function handle(GetResponseEvent $event) { @@ -102,6 +104,9 @@ class SwitchUserListener implements ListenerInterface * @param Request $request A Request instance * * @return TokenInterface|null The new TokenInterface if successfully switched, null otherwise + * + * @throws \LogicException + * @throws AccessDeniedException */ private function attemptSwitchUser(Request $request) { @@ -148,6 +153,8 @@ class SwitchUserListener implements ListenerInterface * @param Request $request A Request instance * * @return TokenInterface The original TokenInterface instance + * + * @throws AuthenticationCredentialsNotFoundException */ private function attemptExitUser(Request $request) { diff --git a/Http/Firewall/UsernamePasswordFormAuthenticationListener.php b/Http/Firewall/UsernamePasswordFormAuthenticationListener.php index 35b0b11..81c2b37 100644 --- a/Http/Firewall/UsernamePasswordFormAuthenticationListener.php +++ b/Http/Firewall/UsernamePasswordFormAuthenticationListener.php @@ -13,7 +13,7 @@ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Log\LoggerInterface; +use Psr\Log\LoggerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface; use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface; @@ -37,15 +37,15 @@ class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationL /** * {@inheritdoc} */ - public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, array $options = array(), AuthenticationSuccessHandlerInterface $successHandler = null, AuthenticationFailureHandlerInterface $failureHandler = null, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, CsrfProviderInterface $csrfProvider = null) + public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = array(), LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, CsrfProviderInterface $csrfProvider = null) { - parent::__construct($securityContext, $authenticationManager, $sessionStrategy, $httpUtils, $providerKey, array_merge(array( + parent::__construct($securityContext, $authenticationManager, $sessionStrategy, $httpUtils, $providerKey, $successHandler, $failureHandler, array_merge(array( 'username_parameter' => '_username', 'password_parameter' => '_password', 'csrf_parameter' => '_csrf_token', 'intention' => 'authenticate', 'post_only' => true, - ), $options), $successHandler, $failureHandler, $logger, $dispatcher); + ), $options), $logger, $dispatcher); $this->csrfProvider = $csrfProvider; } @@ -55,7 +55,7 @@ class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationL */ protected function requiresAuthentication(Request $request) { - if ($this->options['post_only'] && !$request->isMethod('post')) { + if ($this->options['post_only'] && !$request->isMethod('POST')) { return false; } @@ -67,14 +67,6 @@ class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationL */ protected function attemptAuthentication(Request $request) { - if ($this->options['post_only'] && 'post' !== strtolower($request->getMethod())) { - if (null !== $this->logger) { - $this->logger->debug(sprintf('Authentication method not supported: %s.', $request->getMethod())); - } - - return null; - } - if (null !== $this->csrfProvider) { $csrfToken = $request->get($this->options['csrf_parameter'], null, true); @@ -83,8 +75,13 @@ class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationL } } - $username = trim($request->get($this->options['username_parameter'], null, true)); - $password = $request->get($this->options['password_parameter'], null, true); + if ($this->options['post_only']) { + $username = trim($request->request->get($this->options['username_parameter'], null, true)); + $password = $request->request->get($this->options['password_parameter'], null, true); + } else { + $username = trim($request->get($this->options['username_parameter'], null, true)); + $password = $request->get($this->options['password_parameter'], null, true); + } $request->getSession()->set(SecurityContextInterface::LAST_USERNAME, $username); diff --git a/Http/Firewall/X509AuthenticationListener.php b/Http/Firewall/X509AuthenticationListener.php index 2f4b78a..0b5a6ae 100644 --- a/Http/Firewall/X509AuthenticationListener.php +++ b/Http/Firewall/X509AuthenticationListener.php @@ -13,7 +13,7 @@ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; -use Symfony\Component\HttpKernel\Log\LoggerInterface; +use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Exception\BadCredentialsException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; diff --git a/Http/FirewallMapInterface.php b/Http/FirewallMapInterface.php index 5a42ff1..336125f 100644 --- a/Http/FirewallMapInterface.php +++ b/Http/FirewallMapInterface.php @@ -34,5 +34,5 @@ interface FirewallMapInterface * * @return array of the format array(array(AuthenticationListener), ExceptionListener) */ - function getListeners(Request $request); + public function getListeners(Request $request); } diff --git a/Http/HttpUtils.php b/Http/HttpUtils.php index 1c87e77..0453520 100644 --- a/Http/HttpUtils.php +++ b/Http/HttpUtils.php @@ -16,6 +16,7 @@ use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\Routing\Matcher\UrlMatcherInterface; +use Symfony\Component\Routing\Matcher\RequestMatcherInterface; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; @@ -33,12 +34,15 @@ class HttpUtils /** * Constructor. * - * @param UrlGeneratorInterface $urlGenerator A UrlGeneratorInterface instance - * @param UrlMatcherInterface $urlMatcher A UrlMatcherInterface instance + * @param UrlGeneratorInterface $urlGenerator A UrlGeneratorInterface instance + * @param UrlMatcherInterface|RequestMatcherInterface $urlMatcher The Url or Request matcher */ - public function __construct(UrlGeneratorInterface $urlGenerator = null, UrlMatcherInterface $urlMatcher = null) + public function __construct(UrlGeneratorInterface $urlGenerator = null, $urlMatcher = null) { $this->urlGenerator = $urlGenerator; + if ($urlMatcher !== null && !$urlMatcher instanceof UrlMatcherInterface && !$urlMatcher instanceof RequestMatcherInterface) { + throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.'); + } $this->urlMatcher = $urlMatcher; } @@ -66,9 +70,9 @@ class HttpUtils */ public function createRequest(Request $request, $path) { - $newRequest = Request::create($this->generateUri($request, $path), 'get', array(), $request->cookies->all(), array(), $request->server->all()); - if ($session = $request->getSession()) { - $newRequest->setSession($session); + $newRequest = $request::create($this->generateUri($request, $path), 'get', array(), $request->cookies->all(), array(), $request->server->all()); + if ($request->hasSession()) { + $newRequest->setSession($request->getSession()); } if ($request->attributes->has(SecurityContextInterface::AUTHENTICATION_ERROR)) { @@ -96,7 +100,12 @@ class HttpUtils { if ('/' !== $path[0]) { try { - $parameters = $this->urlMatcher->match($request->getPathInfo()); + // matching a request is more powerful than matching a URL path + context, so try that first + if ($this->urlMatcher instanceof RequestMatcherInterface) { + $parameters = $this->urlMatcher->matchRequest($request); + } else { + $parameters = $this->urlMatcher->match($request->getPathInfo()); + } return $path === $parameters['_route']; } catch (MethodNotAllowedException $e) { @@ -106,7 +115,7 @@ class HttpUtils } } - return $path === $request->getPathInfo(); + return $path === rawurldecode($request->getPathInfo()); } /** @@ -127,15 +136,20 @@ class HttpUtils return $request->getUriForPath($path); } - return $this->generateUrl($path, true); - } - - private function generateUrl($route, $absolute = false) - { if (null === $this->urlGenerator) { throw new \LogicException('You must provide a UrlGeneratorInterface instance to be able to use routes.'); } - return $this->urlGenerator->generate($route, array(), $absolute); + $url = $this->urlGenerator->generate($path, $request->attributes->all(), UrlGeneratorInterface::ABSOLUTE_URL); + + // unnecessary query string parameters must be removed from url + // (ie. query parameters that are presents in $attributes) + // fortunately, they all are, so we have to remove entire query string + $position = strpos($url, '?'); + if (false !== $position) { + $url = substr($url, 0, $position); + } + + return $url; } } diff --git a/Http/Logout/DefaultLogoutSuccessHandler.php b/Http/Logout/DefaultLogoutSuccessHandler.php new file mode 100644 index 0000000..e06cb6d --- /dev/null +++ b/Http/Logout/DefaultLogoutSuccessHandler.php @@ -0,0 +1,47 @@ +<?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\Http\Logout; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Http\HttpUtils; +use Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface; + +/** + * Default logout success handler will redirect users to a configured path. + * + * @author Fabien Potencier <fabien@symfony.com> + * @author Alexander <iam.asm89@gmail.com> + */ +class DefaultLogoutSuccessHandler implements LogoutSuccessHandlerInterface +{ + protected $httpUtils; + protected $targetUrl; + + /** + * @param HttpUtils $httpUtils + * @param string $targetUrl + */ + public function __construct(HttpUtils $httpUtils, $targetUrl = '/') + { + $this->httpUtils = $httpUtils; + + $this->targetUrl = $targetUrl; + } + + /** + * {@inheritDoc} + */ + public function onLogoutSuccess(Request $request) + { + return $this->httpUtils->createRedirectResponse($request, $this->targetUrl); + } +} diff --git a/Http/Logout/LogoutHandlerInterface.php b/Http/Logout/LogoutHandlerInterface.php index 71be388..5e1cea8 100644 --- a/Http/Logout/LogoutHandlerInterface.php +++ b/Http/Logout/LogoutHandlerInterface.php @@ -31,5 +31,5 @@ interface LogoutHandlerInterface * @param Response $response * @param TokenInterface $token */ - function logout(Request $request, Response $response, TokenInterface $token); + public function logout(Request $request, Response $response, TokenInterface $token); } diff --git a/Http/Logout/LogoutSuccessHandlerInterface.php b/Http/Logout/LogoutSuccessHandlerInterface.php index fb1dd64..61642a8 100644 --- a/Http/Logout/LogoutSuccessHandlerInterface.php +++ b/Http/Logout/LogoutSuccessHandlerInterface.php @@ -33,5 +33,5 @@ interface LogoutSuccessHandlerInterface * * @return Response never null */ - function onLogoutSuccess(Request $request); + public function onLogoutSuccess(Request $request); } diff --git a/Http/RememberMe/AbstractRememberMeServices.php b/Http/RememberMe/AbstractRememberMeServices.php index d61a6ce..ae61dd7 100644 --- a/Http/RememberMe/AbstractRememberMeServices.php +++ b/Http/RememberMe/AbstractRememberMeServices.php @@ -22,7 +22,7 @@ use Symfony\Component\Security\Core\Exception\CookieTheftException; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Cookie; -use Symfony\Component\HttpKernel\Log\LoggerInterface; +use Psr\Log\LoggerInterface; /** * Base class implementing the RememberMeServicesInterface @@ -47,6 +47,8 @@ abstract class AbstractRememberMeServices implements RememberMeServicesInterface * @param string $providerKey * @param array $options * @param LoggerInterface $logger + * + * @throws \InvalidArgumentException */ public function __construct(array $userProviders, $key, $providerKey, array $options = array(), LoggerInterface $logger = null) { @@ -89,9 +91,11 @@ abstract class AbstractRememberMeServices implements RememberMeServicesInterface * * @param Request $request * - * @return TokenInterface + * @return TokenInterface|null + * + * @throws CookieTheftException */ - public final function autoLogin(Request $request) + final public function autoLogin(Request $request) { if (null === $cookie = $request->cookies->get($this->options['name'])) { return; @@ -125,7 +129,7 @@ abstract class AbstractRememberMeServices implements RememberMeServicesInterface } } catch (UnsupportedUserException $unSupported) { if (null !== $this->logger) { - $this->logger->warn('User class for remember-me cookie not supported.'); + $this->logger->warning('User class for remember-me cookie not supported.'); } } catch (AuthenticationException $invalid) { if (null !== $this->logger) { @@ -156,7 +160,7 @@ abstract class AbstractRememberMeServices implements RememberMeServicesInterface * * @param Request $request */ - public final function loginFail(Request $request) + final public function loginFail(Request $request) { $this->cancelCookie($request); $this->onLoginFail($request); @@ -170,8 +174,11 @@ abstract class AbstractRememberMeServices implements RememberMeServicesInterface * @param Response $response * @param TokenInterface $token The token that resulted in a successful authentication */ - public final function loginSuccess(Request $request, Response $response, TokenInterface $token) + 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 +199,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); } @@ -221,7 +234,7 @@ abstract class AbstractRememberMeServices implements RememberMeServicesInterface */ abstract protected function onLoginSuccess(Request $request, Response $response, TokenInterface $token); - protected final function getUserProvider($class) + final protected function getUserProvider($class) { foreach ($this->userProviders as $provider) { if ($provider->supportsClass($class)) { diff --git a/Http/RememberMe/PersistentTokenBasedRememberMeServices.php b/Http/RememberMe/PersistentTokenBasedRememberMeServices.php index 8944672..9f4013d 100644 --- a/Http/RememberMe/PersistentTokenBasedRememberMeServices.php +++ b/Http/RememberMe/PersistentTokenBasedRememberMeServices.php @@ -19,6 +19,7 @@ use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\CookieTheftException; use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\Security\Core\Util\SecureRandomInterface; /** * Concrete implementation of the RememberMeServicesInterface which needs @@ -30,6 +31,24 @@ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices { private $tokenProvider; + private $secureRandom; + + /** + * Constructor. + * + * @param array $userProviders + * @param string $key + * @param string $providerKey + * @param array $options + * @param LoggerInterface $logger + * @param SecureRandomInterface $secureRandom + */ + public function __construct(array $userProviders, $key, $providerKey, array $options = array(), LoggerInterface $logger = null, SecureRandomInterface $secureRandom) + { + parent::__construct($userProviders, $key, $providerKey, $options, $logger); + + $this->secureRandom = $secureRandom; + } /** * Sets the token provider @@ -44,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 ) { @@ -69,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.'); } @@ -79,7 +98,7 @@ class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices } $series = $persistentToken->getSeries(); - $tokenValue = $this->generateRandomValue(); + $tokenValue = $this->secureRandom->nextBytes(64); $this->tokenProvider->updateToken($series, $tokenValue, new \DateTime()); $request->attributes->set(self::COOKIE_ATTR_NAME, new Cookie( @@ -101,8 +120,8 @@ class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices */ protected function onLoginSuccess(Request $request, Response $response, TokenInterface $token) { - $series = $this->generateRandomValue(); - $tokenValue = $this->generateRandomValue(); + $series = $this->secureRandom->nextBytes(64); + $tokenValue = $this->secureRandom->nextBytes(64); $this->tokenProvider->createNewToken( new PersistentToken( @@ -126,26 +145,4 @@ class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices ) ); } - - /** - * Generates a cryptographically strong random value - * - * @return string - */ - protected function generateRandomValue() - { - if (function_exists('openssl_random_pseudo_bytes')) { - $bytes = openssl_random_pseudo_bytes(64, $strong); - - if (true === $strong && false !== $bytes) { - return base64_encode($bytes); - } - } - - if (null !== $this->logger) { - $this->logger->warn('Could not produce a cryptographically strong random value. Please install/update the OpenSSL extension.'); - } - - return base64_encode(hash('sha512', uniqid(mt_rand(), true), true)); - } } diff --git a/Http/RememberMe/RememberMeServicesInterface.php b/Http/RememberMe/RememberMeServicesInterface.php index 0497c69..a00dcef 100644 --- a/Http/RememberMe/RememberMeServicesInterface.php +++ b/Http/RememberMe/RememberMeServicesInterface.php @@ -51,7 +51,7 @@ interface RememberMeServicesInterface * * @return TokenInterface */ - function autoLogin(Request $request); + public function autoLogin(Request $request); /** * Called whenever an interactive authentication attempt was made, but the @@ -61,7 +61,7 @@ interface RememberMeServicesInterface * * @param Request $request */ - function loginFail(Request $request); + public function loginFail(Request $request); /** * Called whenever an interactive authentication attempt is successful @@ -78,5 +78,5 @@ interface RememberMeServicesInterface * @param Response $response * @param TokenInterface $token */ - function loginSuccess(Request $request, Response $response, TokenInterface $token); + public function loginSuccess(Request $request, Response $response, TokenInterface $token); } diff --git a/Http/RememberMe/ResponseListener.php b/Http/RememberMe/ResponseListener.php new file mode 100644 index 0000000..03c71c7 --- /dev/null +++ b/Http/RememberMe/ResponseListener.php @@ -0,0 +1,39 @@ +<?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\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 implements EventSubscriberInterface +{ + public function onKernelResponse(FilterResponseEvent $event) + { + $request = $event->getRequest(); + $response = $event->getResponse(); + + if ($request->attributes->has(RememberMeServicesInterface::COOKIE_ATTR_NAME)) { + $response->headers->setCookie($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)); + } + } + + public static function getSubscribedEvents() + { + return array(KernelEvents::RESPONSE => 'onKernelResponse'); + } +} diff --git a/Http/RememberMe/TokenBasedRememberMeServices.php b/Http/RememberMe/TokenBasedRememberMeServices.php index bd828f2..5a66fe4 100644 --- a/Http/RememberMe/TokenBasedRememberMeServices.php +++ b/Http/RememberMe/TokenBasedRememberMeServices.php @@ -43,7 +43,7 @@ class TokenBasedRememberMeServices extends AbstractRememberMeServices $user = $this->getUserProvider($class)->loadUserByUsername($username); } catch (\Exception $ex) { if (!$ex instanceof AuthenticationException) { - $ex = new AuthenticationException($ex->getMessage(), null, $ex->getCode(), $ex); + $ex = new AuthenticationException($ex->getMessage(), $ex->getCode(), $ex); } throw $ex; diff --git a/Http/SecurityEvents.php b/Http/SecurityEvents.php index a6c4e42..45fae29 100644 --- a/Http/SecurityEvents.php +++ b/Http/SecurityEvents.php @@ -13,7 +13,25 @@ namespace Symfony\Component\Security\Http; final class SecurityEvents { + /** + * The INTERACTIVE_LOGIN event occurs after a user is logged in + * interactively for authentication based on http, cookies or X509. + * + * The event listener method receives a + * Symfony\Component\Security\Http\Event\InteractiveLoginEvent instance. + * + * @var string + */ const INTERACTIVE_LOGIN = 'security.interactive_login'; + /** + * The SWITCH_USER event occurs before switch to another user and + * before exit from an already switched user. + * + * The event listener method receives a + * Symfony\Component\Security\Http\Event\SwitchUserEvent instance. + * + * @var string + */ const SWITCH_USER = 'security.switch_user'; } diff --git a/Http/Session/SessionAuthenticationStrategyInterface.php b/Http/Session/SessionAuthenticationStrategyInterface.php index 34f5089..2bc292b 100644 --- a/Http/Session/SessionAuthenticationStrategyInterface.php +++ b/Http/Session/SessionAuthenticationStrategyInterface.php @@ -33,5 +33,5 @@ interface SessionAuthenticationStrategyInterface * @param Request $request * @param TokenInterface $token */ - function onAuthentication(Request $request, TokenInterface $token); + public function onAuthentication(Request $request, TokenInterface $token); } @@ -1,4 +1,4 @@ -Copyright (c) 2004-2012 Fabien Potencier +Copyright (c) 2004-2013 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -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/Resources/translations/security.ar.xlf b/Resources/translations/security.ar.xlf new file mode 100644 index 0000000..fd18ee6 --- /dev/null +++ b/Resources/translations/security.ar.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>حدث خطأ اثناء الدخول.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>لم استطع العثور على معلومات الدخول.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>لم يكتمل طلب الدخول نتيجه عطل فى النظام.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>معلومات الدخول خاطئة.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>ملفات تعريف الارتباط(cookies) تم استخدامها من قبل شخص اخر.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>ليست لديك الصلاحيات الكافية لهذا الطلب.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>رمز الموقع غير صحيح.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>انتهت صلاحية(digest nonce).</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>لا يوجد معرف للدخول يدعم الرمز المستخدم للدخول.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>لا يوجد صلة بينك و بين الموقع اما انها انتهت او ان متصفحك لا يدعم خاصية ملفات تعريف الارتباط (cookies).</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>لم استطع العثور على الرمز.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>لم استطع العثور على اسم الدخول.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>انتهت صلاحية الحساب.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>انتهت صلاحية معلومات الدخول.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>الحساب موقوف.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>الحساب مغلق.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.ca.xlf b/Resources/translations/security.ca.xlf new file mode 100644 index 0000000..7ece260 --- /dev/null +++ b/Resources/translations/security.ca.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>Ha succeït un error d'autenticació.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>No s'han trobat les credencials d'autenticació.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>La solicitud d'autenticació no s'ha pogut processar per un problema del sistema.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Credencials no vàlides.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>La cookie ja ha estat utilitzada per una altra persona.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>No té privilegis per solicitar el recurs.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Token CSRF no vàlid.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>El vector d'inicialització (digest nonce) ha expirat.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>No s'ha trobat un proveïdor d'autenticació que suporti el token d'autenticació.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>No hi ha sessió disponible, ha expirat o les cookies no estan habilitades.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>No s'ha trobat cap token.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>No s'ha trobat el nom d'usuari.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>El compte ha expirat.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>Les credencials han expirat.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>El compte està deshabilitat.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>El compte està bloquejat.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.cs.xlf b/Resources/translations/security.cs.xlf new file mode 100644 index 0000000..bd146c6 --- /dev/null +++ b/Resources/translations/security.cs.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>Při ověřování došlo k chybě.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>Ověřovací údaje nebyly nalezeny.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>Požadavek na ověření nemohl být zpracován kvůli systémové chybě.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Neplatné přihlašovací údaje.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>Cookie již bylo použité někým jiným.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Nemáte oprávnění přistupovat k prostředku.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Neplatný CSRF token.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>Platnost inicializačního vektoru (digest nonce) vypršela.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>Poskytovatel pro ověřovací token nebyl nalezen.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>Session není k dispozici, vypršela její platnost, nebo jsou zakázané cookies.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>Token nebyl nalezen.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>Přihlašovací jméno nebylo nalezeno.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>Platnost účtu vypršela.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>Platnost přihlašovacích údajů vypršela.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>Účet je zakázaný.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>Účet je zablokovaný.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.da.xlf b/Resources/translations/security.da.xlf new file mode 100644 index 0000000..9c7b886 --- /dev/null +++ b/Resources/translations/security.da.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="no" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>En fejl indtraf ved godkendelse.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>Loginoplysninger kan findes.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>Godkendelsesanmodning kan ikke behandles på grund af et systemfejl.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Ugyldige loginoplysninger.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>Cookie er allerede brugt af en anden.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Ingen tilladselese at anvende kilden.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Ugyldigt CSRF token.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>Digest nonce er udløbet.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>Ingen godkendelsesudbyder er fundet til understøttelsen af godkendelsestoken.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>Ingen session tilgængelig, sessionen er enten udløbet eller cookies er ikke aktiveret.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>Ingen token kan findes.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>Brugernavn kan ikke findes.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>Brugerkonto er udløbet.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>Loginoplysninger er udløbet.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>Brugerkonto er deaktiveret.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>Brugerkonto er låst.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.de.xlf b/Resources/translations/security.de.xlf new file mode 100644 index 0000000..e5946ed --- /dev/null +++ b/Resources/translations/security.de.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>Es ist ein Fehler bei der Authentifikation aufgetreten.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>Es konnten keine Zugangsdaten gefunden werden.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>Die Authentifikation konnte wegen eines Systemproblems nicht bearbeitet werden.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Fehlerhafte Zugangsdaten.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>Cookie wurde bereits von jemand anderem verwendet.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Keine Rechte, um die Ressource anzufragen.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Ungültiges CSRF-Token.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>Digest nonce ist abgelaufen.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>Es wurde kein Authentifizierungs-Provider gefunden, der das Authentifizierungs-Token unterstützt.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>Keine Session verfügbar, entweder ist diese abgelaufen oder Cookies sind nicht aktiviert.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>Es wurde kein Token gefunden.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>Der Benutzername wurde nicht gefunden.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>Der Account ist abgelaufen.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>Die Zugangsdaten sind abgelaufen.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>Der Account ist deaktiviert.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>Der Account ist gesperrt.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.en.xlf b/Resources/translations/security.en.xlf new file mode 100644 index 0000000..3640698 --- /dev/null +++ b/Resources/translations/security.en.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>An authentication exception occurred.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>Authentication credentials could not be found.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>Authentication request could not be processed due to a system problem.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Invalid credentials.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>Cookie has already been used by someone else.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Not privileged to request the resource.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Invalid CSRF token.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>Digest nonce has expired.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>No authentication provider found to support the authentication token.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>No session available, it either timed out or cookies are not enabled.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>No token could be found.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>Username could not be found.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>Account has expired.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>Credentials have expired.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>Account is disabled.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>Account is locked.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.es.xlf b/Resources/translations/security.es.xlf new file mode 100644 index 0000000..00cefbb --- /dev/null +++ b/Resources/translations/security.es.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>Ocurrió un error de autenticación.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>No se encontraron las credenciales de autenticación.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>La solicitud de autenticación no se pudo procesar debido a un problema del sistema.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Credenciales no válidas.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>La cookie ya ha sido usada por otra persona.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>No tiene privilegios para solicitar el recurso.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Token CSRF no válido.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>El vector de inicialización (digest nonce) ha expirado.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>No se encontró un proveedor de autenticación que soporte el token de autenticación.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>No hay ninguna sesión disponible, ha expirado o las cookies no están habilitados.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>No se encontró ningún token.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>No se encontró el nombre de usuario.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>La cuenta ha expirado.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>Las credenciales han expirado.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>La cuenta está deshabilitada.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>La cuenta está bloqueada.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.fa.xlf b/Resources/translations/security.fa.xlf new file mode 100644 index 0000000..0b76290 --- /dev/null +++ b/Resources/translations/security.fa.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>خطایی هنگام تعیین اعتبار اتفاق افتاد.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>شرایط تعیین اعتبار پیدا نشد.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>درخواست تعیین اعتبار به دلیل مشکل سیستم قابل بررسی نیست.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>شرایط نامعتبر.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>کوکی قبلا برای شخص دیگری استفاده شده است.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>دسترسی لازم برای درخواست این منبع را ندارید.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>توکن CSRF معتبر نیست.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>Digest nonce منقضی شده است.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>هیچ ارایه کننده تعیین اعتباری برای ساپورت توکن تعیین اعتبار پیدا نشد.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>جلسهای در دسترس نیست. این میتواند یا به دلیل پایان یافتن زمان باشد یا اینکه کوکی ها فعال نیستند.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>هیچ توکنی پیدا نشد.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>نام کاربری پیدا نشد.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>حساب کاربری منقضی شده است.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>پارامترهای تعیین اعتبار منقضی شدهاند.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>حساب کاربری غیرفعال است.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>حساب کاربری قفل شده است.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.fr.xlf b/Resources/translations/security.fr.xlf new file mode 100644 index 0000000..f3965d3 --- /dev/null +++ b/Resources/translations/security.fr.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>Une exception d'authentification s'est produite.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>Les droits d'authentification n'ont pas pu être trouvés.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>La requête d'authentification n'a pas pu être executée à cause d'un problème système.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Droits invalides.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>Le cookie a déjà été utilisé par quelqu'un d'autre.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Pas de privilèges pour accéder à la ressource.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Jeton CSRF invalide.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>Le digest nonce a expiré.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>Aucun fournisseur d'authentification n'a été trouvé pour supporter le jeton d'authentification.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>Pas de session disponible, celle-ci a expiré ou les cookies ne sont pas activés.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>Aucun jeton n'a pu être trouvé.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>Le nom d'utilisateur ne peut pas être trouvé.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>Le compte a expiré.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>Les droits ont expirés.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>Le compte est désactivé.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>Le compte est bloqué.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.gl.xlf b/Resources/translations/security.gl.xlf new file mode 100644 index 0000000..ed6491f --- /dev/null +++ b/Resources/translations/security.gl.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>Ocorreu un erro de autenticación.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>Non se atoparon as credenciais de autenticación.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>A solicitude de autenticación no puido ser procesada debido a un problema do sistema.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Credenciais non válidas.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>A cookie xa foi empregado por outro usuario.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Non ten privilexios para solicitar o recurso.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Token CSRF non válido.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>O vector de inicialización (digest nonce) expirou.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>Non se atopou un provedor de autenticación que soporte o token de autenticación.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>Non hai ningunha sesión dispoñible, expirou ou as cookies non están habilitadas.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>Non se atopou ningún token.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>Non se atopou o nome de usuario.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>A conta expirou.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>As credenciais expiraron.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>A conta está deshabilitada.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>A conta está bloqueada.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.hu.xlf b/Resources/translations/security.hu.xlf new file mode 100644 index 0000000..7243970 --- /dev/null +++ b/Resources/translations/security.hu.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>Hitelesítési hiba lépett fel.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>Nem találhatók hitelesítési információk.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>A hitelesítési kérést rendszerhiba miatt nem lehet feldolgozni.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Érvénytelen hitelesítési információk.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>Ezt a sütit valaki más már felhasználta.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Nem rendelkezik az erőforrás eléréséhez szükséges jogosultsággal.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Érvénytelen CSRF token.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>A kivonat bélyege (nonce) lejárt.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>Nem található a hitelesítési tokent támogató hitelesítési szolgáltatás.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>Munkamenet nem áll rendelkezésre, túllépte az időkeretet vagy a sütik le vannak tiltva.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>Nem található token.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>A felhasználónév nem található.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>A fiók lejárt.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>A hitelesítési információk lejártak.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>Felfüggesztett fiók.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>Zárolt fiók.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.it.xlf b/Resources/translations/security.it.xlf new file mode 100644 index 0000000..75d81cc --- /dev/null +++ b/Resources/translations/security.it.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>Si è verificato un errore di autenticazione.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>Impossibile trovare le credenziali di autenticazione.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>La richiesta di autenticazione non può essere processata a causa di un errore di sistema.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Credenziali non valide.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>Il cookie è già stato usato da qualcun altro.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Non hai i privilegi per richiedere questa risorsa.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>CSRF token non valido.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>Il numero di autenticazione è scaduto.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>Non è stato trovato un valido fornitore di autenticazione per supportare il token.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>Nessuna sessione disponibile, può essere scaduta o i cookie non sono abilitati.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>Nessun token trovato.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>Username non trovato.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>Account scaduto.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>Credenziali scadute.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>L'account è disabilitato.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>L'account è bloccato.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.lb.xlf b/Resources/translations/security.lb.xlf new file mode 100644 index 0000000..3dc76d5 --- /dev/null +++ b/Resources/translations/security.lb.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" target-language="lb" datatype="plaintext" original="security.en.xlf"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>Bei der Authentifikatioun ass e Feeler opgetrueden.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>Et konnte keng Zouganksdate fonnt ginn.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>D'Ufro fir eng Authentifikatioun konnt wéinst engem Problem vum System net beaarbecht ginn.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Ongëlteg Zouganksdaten.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>De Cookie gouf scho vun engem anere benotzt.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Keng Rechter fir d'Ressource unzefroen.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Ongëltegen CSRF-Token.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>Den eemolege Schlëssel ass ofgelaf.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>Et gouf keen Authentifizéierungs-Provider fonnt deen den Authentifizéierungs-Token ënnerstëtzt.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>Keng Sëtzung disponibel. Entweder ass se ofgelaf oder Cookies sinn net aktivéiert.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>Et konnt keen Token fonnt ginn.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>De Benotzernumm konnt net fonnt ginn.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>Den Account ass ofgelaf.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>D'Zouganksdate sinn ofgelaf.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>De Konto ass deaktivéiert.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>De Konto ass gespaart.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.nl.xlf b/Resources/translations/security.nl.xlf new file mode 100644 index 0000000..8969e9e --- /dev/null +++ b/Resources/translations/security.nl.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>Er heeft zich een authenticatieprobleem voorgedaan.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>Authenticatiegegevens konden niet worden gevonden.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>Authenticatieaanvraag kon niet worden verwerkt door een technisch probleem.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Ongeldige inloggegevens.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>Cookie is al door een ander persoon gebruikt.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Onvoldoende rechten om de aanvraag te verwerken.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>CSRF-code is ongeldig.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>Serverauthenticatiesleutel (digest nonce) is verlopen.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>Geen authenticatieprovider gevonden die de authenticatietoken ondersteunt.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>Geen sessie beschikbaar, mogelijk is deze verlopen of cookies zijn uitgeschakeld.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>Er kon geen authenticatietoken worden gevonden.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>Gebruikersnaam kon niet worden gevonden.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>Account is verlopen.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>Authenticatiegegevens zijn verlopen.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>Account is gedeactiveerd.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>Account is geblokkeerd.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.no.xlf b/Resources/translations/security.no.xlf new file mode 100644 index 0000000..3857ab4 --- /dev/null +++ b/Resources/translations/security.no.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="no" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>En autentiserings feil har skjedd.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>Påloggingsinformasjonen kunne ikke bli funnet.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>Autentiserings forespørselen kunne ikke bli prosessert grunnet en system feil.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Ugyldig påloggingsinformasjonen.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>Cookie har allerede blitt brukt av noen andre.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Ingen tilgang til å be om gitt kilde.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Ugyldig CSRF token.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>Digest nonce er utløpt.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>Ingen autentiserings tilbyder funnet som støtter gitt autentiserings token.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>Ingen sesjon tilgjengelig, sesjonen er enten utløpt eller cookies ikke skrudd på.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>Ingen token kunne bli funnet.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>Brukernavn kunne ikke bli funnet.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>Brukerkonto har utgått.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>Påloggingsinformasjon har utløpt.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>Brukerkonto er deaktivert.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>Brukerkonto er sperret.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.pl.xlf b/Resources/translations/security.pl.xlf new file mode 100644 index 0000000..8d563d2 --- /dev/null +++ b/Resources/translations/security.pl.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>Wystąpił błąd uwierzytelniania.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>Dane uwierzytelniania nie zostały znalezione.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>Żądanie uwierzytelniania nie mogło zostać pomyślnie zakończone z powodu problemu z systemem.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Nieprawidłowe dane.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>To ciasteczko jest używane przez kogoś innego.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Brak uprawnień dla żądania wskazanego zasobu.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Nieprawidłowy token CSRF.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>Kod dostępu wygasł.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>Nie znaleziono mechanizmu uwierzytelniania zdolnego do obsługi przesłanego tokenu.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>Brak danych sesji, sesja wygasła lub ciasteczka nie są włączone.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>Nie znaleziono tokenu.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>Użytkownik o podanej nazwie nie istnieje.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>Konto wygasło.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>Dane uwierzytelniania wygasły.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>Konto jest wyłączone.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>Konto jest zablokowane.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.pt_BR.xlf b/Resources/translations/security.pt_BR.xlf new file mode 100644 index 0000000..846fd49 --- /dev/null +++ b/Resources/translations/security.pt_BR.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>Uma exceção ocorreu durante a autenticação.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>As credenciais de autenticação não foram encontradas.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>A autenticação não pôde ser concluída devido a um problema no sistema.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Credenciais inválidas.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>Este cookie já esta em uso.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Não possui privilégios o bastante para requisitar este recurso.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Token CSRF inválido.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>Digest nonce expirado.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>Nenhum provedor de autenticação encontrado para suportar o token de autenticação.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>Nenhuma sessão disponível, ela expirou ou cookies estão desativados.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>Nenhum token foi encontrado.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>Nome de usuário não encontrado.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>A conta esta expirada.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>As credenciais estão expiradas.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>Conta desativada.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>A conta esta travada.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.pt_PT.xlf b/Resources/translations/security.pt_PT.xlf new file mode 100644 index 0000000..e661000 --- /dev/null +++ b/Resources/translations/security.pt_PT.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>Ocorreu um excepção durante a autenticação.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>As credenciais de autenticação não foram encontradas.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>O pedido de autenticação não foi concluído devido a um problema no sistema.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Credenciais inválidas.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>Este cookie já esta em uso.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Não possui privilégios para aceder a este recurso.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Token CSRF inválido.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>Digest nonce expirado.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>Nenhum fornecedor de autenticação encontrado para suportar o token de autenticação.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>Não existe sessão disponível, esta expirou ou os cookies estão desativados.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>O token não foi encontrado.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>Nome de utilizador não encontrado.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>A conta expirou.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>As credenciais expiraram.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>Conta desativada.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>A conta esta trancada.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.ro.xlf b/Resources/translations/security.ro.xlf new file mode 100644 index 0000000..440f110 --- /dev/null +++ b/Resources/translations/security.ro.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>A apărut o eroare de autentificare.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>Informațiile de autentificare nu au fost găsite.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>Sistemul nu a putut procesa cererea de autentificare din cauza unei erori.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Date de autentificare invalide.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>Cookieul este folosit deja de altcineva.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Permisiuni insuficiente pentru resursa cerută.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Tokenul CSRF este invalid.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>Tokenul temporar a expirat.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>Nu a fost găsit nici un agent de autentificare pentru tokenul specificat.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>Sesiunea nu mai este disponibilă, a expirat sau suportul pentru cookieuri nu este activat.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>Tokenul nu a putut fi găsit.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>Numele de utilizator nu a fost găsit.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>Contul a expirat.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>Datele de autentificare au expirat.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>Contul este dezactivat.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>Contul este blocat.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.ru.xlf b/Resources/translations/security.ru.xlf new file mode 100644 index 0000000..1964f95 --- /dev/null +++ b/Resources/translations/security.ru.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>Ошибка аутентификации.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>Аутентификационные данные не найдены.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>Запрос аутентификации не может быть обработан в связи с проблемой в системе.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Недействительные аутентификационные данные.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>Cookie уже был использован кем-то другим.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Отсутствуют права на запрос этого ресурса.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Недействительный токен CSRF.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>Время действия одноразового ключа дайджеста истекло.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>Не найден провайдер аутентификации, поддерживающий токен аутентификации.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>Сессия не найдена, ее время истекло, либо cookies не включены.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>Токен не найден.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>Имя пользователя не найдено.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>Время действия учетной записи истекло.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>Время действия аутентификационных данных истекло.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>Учетная запись отключена.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>Учетная запись заблокирована.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.sk.xlf b/Resources/translations/security.sk.xlf new file mode 100644 index 0000000..e6552a6 --- /dev/null +++ b/Resources/translations/security.sk.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>Pri overovaní došlo k chybe.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>Overovacie údaje neboli nájdené.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>Požiadavok na overenie nemohol byť spracovaný kvôli systémovej chybe.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Neplatné prihlasovacie údaje.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>Cookie už bolo použité niekým iným.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Nemáte oprávnenie pristupovať k prostriedku.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Neplatný CSRF token.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>Platnosť inicializačného vektoru (digest nonce) skončila.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>Poskytovateľ pre overovací token nebol nájdený.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>Session nie je k dispozíci, vypršala jej platnosť, alebo sú zakázané cookies.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>Token nebol nájdený.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>Prihlasovacie meno nebolo nájdené.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>Platnosť účtu skončila.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>Platnosť prihlasovacích údajov skončila.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>Účet je zakázaný.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>Účet je zablokovaný.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.sl.xlf b/Resources/translations/security.sl.xlf new file mode 100644 index 0000000..ee70c9a --- /dev/null +++ b/Resources/translations/security.sl.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>Prišlo je do izjeme pri preverjanju avtentikacije.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>Poverilnic za avtentikacijo ni bilo mogoče najti.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>Zahteve za avtentikacijo ni bilo mogoče izvesti zaradi sistemske težave.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Neveljavne pravice.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>Piškotek je uporabil že nekdo drug.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Nimate privilegijev za zahtevani vir.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Neveljaven CSRF žeton.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>Začasni žeton je potekel.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>Ponudnika avtentikacije za podporo prijavnega žetona ni bilo mogoče najti.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>Seja ni na voljo, ali je potekla ali pa piškotki niso omogočeni.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>Žetona ni bilo mogoče najti.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>Uporabniškega imena ni bilo mogoče najti.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>Račun je potekel.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>Poverilnice so potekle.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>Račun je onemogočen.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>Račun je zaklenjen.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.sr_Cyrl.xlf b/Resources/translations/security.sr_Cyrl.xlf new file mode 100644 index 0000000..35e4ddf --- /dev/null +++ b/Resources/translations/security.sr_Cyrl.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>Изузетак при аутентификацији.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>Аутентификациони подаци нису пронађени.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>Захтев за аутентификацију не може бити обрађен због системских проблема.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Невалидни подаци за аутентификацију.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>Колачић је већ искоришћен од стране неког другог.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Немате права приступа овом ресурсу.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Невалидан CSRF токен.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>Време криптографског кључа је истекло.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>Аутентификациони провајдер за подршку токена није пронађен.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>Сесија није доступна, истекла је или су колачићи искључени.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>Токен не може бити пронађен.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>Корисничко име не може бити пронађено.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>Налог је истекао.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>Подаци за аутентификацију су истекли.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>Налог је онемогућен.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>Налог је закључан.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.sr_Latn.xlf b/Resources/translations/security.sr_Latn.xlf new file mode 100644 index 0000000..ddc4807 --- /dev/null +++ b/Resources/translations/security.sr_Latn.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>Izuzetak pri autentifikaciji.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>Autentifikacioni podaci nisu pronađeni.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>Zahtev za autentifikaciju ne može biti obrađen zbog sistemskih problema.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Nevalidni podaci za autentifikaciju.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>Kolačić je već iskorišćen od strane nekog drugog.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Nemate prava pristupa ovom resursu.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Nevalidan CSRF token.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>Vreme kriptografskog ključa je isteklo.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>Autentifikacioni provajder za podršku tokena nije pronađen.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>Sesija nije dostupna, istekla je ili su kolačići isključeni.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>Token ne može biti pronađen.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>Korisničko ime ne može biti pronađeno.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>Nalog je istekao.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>Podaci za autentifikaciju su istekli.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>Nalog je onemogućen.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>Nalog je zaključan.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.sv.xlf b/Resources/translations/security.sv.xlf new file mode 100644 index 0000000..b5f6209 --- /dev/null +++ b/Resources/translations/security.sv.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>Ett autentiseringsfel har inträffat.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>Uppgifterna för autentisering kunde inte hittas.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>Autentiseringen kunde inte genomföras på grund av systemfel.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Felaktiga uppgifter.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>Cookien har redan använts av någon annan.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Saknar rättigheter för resursen.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Ogiltig CSRF-token.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>Förfallen digest nonce.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>Ingen leverantör för autentisering hittades för angiven autentiseringstoken.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>Ingen session finns tillgänglig, antingen har den förfallit eller är cookies inte aktiverat.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>Ingen token kunde hittas.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>Användarnamnet kunde inte hittas.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>Kontot har förfallit.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>Uppgifterna har förfallit.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>Kontot är inaktiverat.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>Kontot är låst.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.tr.xlf b/Resources/translations/security.tr.xlf new file mode 100644 index 0000000..fbf9b26 --- /dev/null +++ b/Resources/translations/security.tr.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>Bir yetkilendirme istisnası oluştu.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>Yetkilendirme girdileri bulunamadı.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>Bir sistem hatası nedeniyle yetkilendirme isteği işleme alınamıyor.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Geçersiz girdiler.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>Çerez bir başkası tarafından zaten kullanılmıştı.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Kaynak talebi için imtiyaz bulunamadı.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Geçersiz CSRF fişi.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>Derleme zaman aşımı gerçekleşti.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>Yetkilendirme fişini destekleyecek yetkilendirme sağlayıcısı bulunamadı.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>Oturum bulunamadı, zaman aşımına uğradı veya çerezler etkin değil.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>Bilet bulunamadı.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>Kullanıcı adı bulunamadı.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>Hesap zaman aşımına uğradı.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>Girdiler zaman aşımına uğradı.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>Hesap devre dışı bırakılmış.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>Hesap kilitlenmiş.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Resources/translations/security.ua.xlf b/Resources/translations/security.ua.xlf new file mode 100644 index 0000000..7972121 --- /dev/null +++ b/Resources/translations/security.ua.xlf @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>Помилка автентифікації.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>Автентифікаційні дані не знайдено.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>Запит на автентифікацію не може бути опрацьовано у зв’язку з проблемою в системі.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Невірні автентифікаційні дані.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>Хтось інший вже використав цей сookie.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Відсутні права на запит цього ресурсу.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Невірний токен CSRF.</target> + </trans-unit> + <trans-unit id="8"> + <source>Digest nonce has expired.</source> + <target>Закінчився термін дії одноразового ключа дайджесту.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>Не знайдено провайдера автентифікації, що підтримує токен автентифікаціії.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>Сесія недоступна, її час вийшов, або cookies вимкнено.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>Токен не знайдено.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>Ім’я користувача не знайдено.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>Термін дії облікового запису вичерпано.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>Термін дії автентифікаційних даних вичерпано.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>Обліковий запис відключено.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>Обліковий запис заблоковано.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/Tests/Acl/Dbal/AclProviderTest.php b/Tests/Acl/Dbal/AclProviderTest.php index e03edc0..83771ee 100644 --- a/Tests/Acl/Dbal/AclProviderTest.php +++ b/Tests/Acl/Dbal/AclProviderTest.php @@ -27,7 +27,7 @@ class AclProviderTest extends \PHPUnit_Framework_TestCase protected $insertSidStmt; /** - * @expectedException Symfony\Component\Security\Acl\Exception\AclNotFoundException + * @expectedException \Symfony\Component\Security\Acl\Exception\AclNotFoundException * @expectedMessage There is no ACL for the given object identity. */ public function testFindAclThrowsExceptionWhenNoAclExists() diff --git a/Tests/Acl/Dbal/MutableAclProviderTest.php b/Tests/Acl/Dbal/MutableAclProviderTest.php index e264b6d..3e8d65f 100644 --- a/Tests/Acl/Dbal/MutableAclProviderTest.php +++ b/Tests/Acl/Dbal/MutableAclProviderTest.php @@ -53,7 +53,7 @@ class MutableAclProviderTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Acl\Exception\AclAlreadyExistsException + * @expectedException \Symfony\Component\Security\Acl\Exception\AclAlreadyExistsException */ public function testCreateAclThrowsExceptionWhenAclAlreadyExists() { @@ -267,7 +267,7 @@ class MutableAclProviderTest extends \PHPUnit_Framework_TestCase $provider->updateAcl($acl); } - public function testUpdateAclThrowsExceptionOnConcurrentModifcationOfSharedProperties() + public function testUpdateAclThrowsExceptionOnConcurrentModificationOfSharedProperties() { $provider = $this->getProvider(); $acl1 = $provider->createAcl(new ObjectIdentity(1, 'Foo')); diff --git a/Tests/Acl/Domain/AclTest.php b/Tests/Acl/Domain/AclTest.php index b6f3d79..4b67e62 100644 --- a/Tests/Acl/Domain/AclTest.php +++ b/Tests/Acl/Domain/AclTest.php @@ -433,7 +433,7 @@ class AclTest extends \PHPUnit_Framework_TestCase * @expectedException \InvalidArgumentException * @dataProvider getUpdateFieldAuditingTests */ - public function testUpdateFieldAuditingthrowsExceptionOnInvalidField($type) + public function testUpdateFieldAuditingThrowsExceptionOnInvalidField($type) { $acl = $this->getAcl(); $acl->{'update'.$type.'Auditing'}(0, 'foo', true, true); diff --git a/Tests/Acl/Domain/PermissionGrantingStrategyTest.php b/Tests/Acl/Domain/PermissionGrantingStrategyTest.php index 67c9f3f..d200d2b 100644 --- a/Tests/Acl/Domain/PermissionGrantingStrategyTest.php +++ b/Tests/Acl/Domain/PermissionGrantingStrategyTest.php @@ -31,7 +31,7 @@ class PermissionGrantingStrategyTest extends \PHPUnit_Framework_TestCase $this->assertFalse($strategy->isGranted($acl, array(1), array($sid))); } - public function testIsGrantedFallsbackToClassAcesIfNoApplicableObjectAceWasFound() + public function testIsGrantedFallsBackToClassAcesIfNoApplicableObjectAceWasFound() { $strategy = new PermissionGrantingStrategy(); $acl = $this->getAcl($strategy); @@ -73,7 +73,7 @@ class PermissionGrantingStrategyTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Acl\Exception\NoAceFoundException + * @expectedException \Symfony\Component\Security\Acl\Exception\NoAceFoundException */ public function testIsGrantedReturnsExceptionIfNoAceIsFound() { diff --git a/Tests/Acl/Domain/SecurityIdentityRetrievalStrategyTest.php b/Tests/Acl/Domain/SecurityIdentityRetrievalStrategyTest.php index 2083728..f649653 100644 --- a/Tests/Acl/Domain/SecurityIdentityRetrievalStrategyTest.php +++ b/Tests/Acl/Domain/SecurityIdentityRetrievalStrategyTest.php @@ -116,7 +116,6 @@ class SecurityIdentityRetrievalStrategyTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue($username)) ; - return $account; } @@ -177,7 +176,6 @@ class SecurityIdentityRetrievalStrategyTest extends \PHPUnit_Framework_TestCase ; } - return new SecurityIdentityRetrievalStrategy($roleHierarchy, $trustResolver); } } diff --git a/Tests/Acl/Domain/UserSecurityIdentityTest.php b/Tests/Acl/Domain/UserSecurityIdentityTest.php index 9650803..1d6a3c5 100644 --- a/Tests/Acl/Domain/UserSecurityIdentityTest.php +++ b/Tests/Acl/Domain/UserSecurityIdentityTest.php @@ -25,7 +25,7 @@ class UserSecurityIdentityTest extends \PHPUnit_Framework_TestCase } // Test that constructor never changes the type, even for proxies - public function testContructorWithProxy() + public function testConstructorWithProxy() { $id = new UserSecurityIdentity('foo', 'Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Tests\Acl\Domain\Foo'); diff --git a/Tests/Core/Authentication/AuthenticationProviderManagerTest.php b/Tests/Core/Authentication/AuthenticationProviderManagerTest.php index c57967b..12eb568 100644 --- a/Tests/Core/Authentication/AuthenticationProviderManagerTest.php +++ b/Tests/Core/Authentication/AuthenticationProviderManagerTest.php @@ -37,7 +37,7 @@ class AuthenticationProviderManagerTest extends \PHPUnit_Framework_TestCase $manager->authenticate($token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')); $this->fail(); } catch (ProviderNotFoundException $e) { - $this->assertSame($token, $e->getExtraInformation()); + $this->assertSame($token, $e->getToken()); } } @@ -51,7 +51,7 @@ class AuthenticationProviderManagerTest extends \PHPUnit_Framework_TestCase $manager->authenticate($token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')); $this->fail(); } catch (AccountStatusException $e) { - $this->assertSame($token, $e->getExtraInformation()); + $this->assertSame($token, $e->getToken()); } } @@ -65,7 +65,7 @@ class AuthenticationProviderManagerTest extends \PHPUnit_Framework_TestCase $manager->authenticate($token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')); $this->fail(); } catch (AuthenticationException $e) { - $this->assertSame($token, $e->getExtraInformation()); + $this->assertSame($token, $e->getToken()); } } diff --git a/Tests/Core/Authentication/Provider/AnonymousAuthenticationProviderTest.php b/Tests/Core/Authentication/Provider/AnonymousAuthenticationProviderTest.php index 0a76724..d0da147 100644 --- a/Tests/Core/Authentication/Provider/AnonymousAuthenticationProviderTest.php +++ b/Tests/Core/Authentication/Provider/AnonymousAuthenticationProviderTest.php @@ -31,7 +31,7 @@ class AnonymousAuthenticationProviderTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\BadCredentialsException + * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException */ public function testAuthenticateWhenKeyIsNotValid() { diff --git a/Tests/Core/Authentication/Provider/DaoAuthenticationProviderTest.php b/Tests/Core/Authentication/Provider/DaoAuthenticationProviderTest.php index 8bff354..8b27061 100644 --- a/Tests/Core/Authentication/Provider/DaoAuthenticationProviderTest.php +++ b/Tests/Core/Authentication/Provider/DaoAuthenticationProviderTest.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Security\Tests\Core\Authentication\Provider; - use Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder; use Symfony\Component\Security\Core\Authentication\Provider\DaoAuthenticationProvider; @@ -19,7 +18,7 @@ use Symfony\Component\Security\Core\Authentication\Provider\DaoAuthenticationPro class DaoAuthenticationProviderTest extends \PHPUnit_Framework_TestCase { /** - * @expectedException Symfony\Component\Security\Core\Exception\AuthenticationServiceException + * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationServiceException */ public function testRetrieveUserWhenProviderDoesNotReturnAnUserInterface() { @@ -31,7 +30,7 @@ class DaoAuthenticationProviderTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\UsernameNotFoundException + * @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException */ public function testRetrieveUserWhenUsernameIsNotFound() { @@ -49,7 +48,7 @@ class DaoAuthenticationProviderTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\AuthenticationServiceException + * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationServiceException */ public function testRetrieveUserWhenAnExceptionOccurs() { @@ -106,7 +105,7 @@ class DaoAuthenticationProviderTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\BadCredentialsException + * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException */ public function testCheckAuthenticationWhenCredentialsAreEmpty() { @@ -162,7 +161,7 @@ class DaoAuthenticationProviderTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\BadCredentialsException + * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException */ public function testCheckAuthenticationWhenCredentialsAreNotValid() { @@ -186,7 +185,7 @@ class DaoAuthenticationProviderTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\BadCredentialsException + * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException */ public function testCheckAuthenticationDoesNotReauthenticateWhenPasswordHasChanged() { diff --git a/Tests/Core/Authentication/Provider/PreAuthenticatedAuthenticationProviderTest.php b/Tests/Core/Authentication/Provider/PreAuthenticatedAuthenticationProviderTest.php index 9476c0d..f7ffb1e 100644 --- a/Tests/Core/Authentication/Provider/PreAuthenticatedAuthenticationProviderTest.php +++ b/Tests/Core/Authentication/Provider/PreAuthenticatedAuthenticationProviderTest.php @@ -42,7 +42,7 @@ class PreAuthenticatedAuthenticationProviderTest extends \PHPUnit_Framework_Test } /** - * @expectedException Symfony\Component\Security\Core\Exception\BadCredentialsException + * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException */ public function testAuthenticateWhenNoUserIsSet() { @@ -70,7 +70,7 @@ class PreAuthenticatedAuthenticationProviderTest extends \PHPUnit_Framework_Test } /** - * @expectedException Symfony\Component\Security\Core\Exception\LockedException + * @expectedException \Symfony\Component\Security\Core\Exception\LockedException */ public function testAuthenticateWhenUserCheckerThrowsException() { diff --git a/Tests/Core/Authentication/Provider/RememberMeAuthenticationProviderTest.php b/Tests/Core/Authentication/Provider/RememberMeAuthenticationProviderTest.php index fcc2514..5e250e0 100644 --- a/Tests/Core/Authentication/Provider/RememberMeAuthenticationProviderTest.php +++ b/Tests/Core/Authentication/Provider/RememberMeAuthenticationProviderTest.php @@ -34,7 +34,7 @@ class RememberMeAuthenticationProviderTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\BadCredentialsException + * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException */ public function testAuthenticateWhenKeysDoNotMatch() { @@ -45,7 +45,7 @@ class RememberMeAuthenticationProviderTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\AccountExpiredException + * @expectedException \Symfony\Component\Security\Core\Exception\AccountExpiredException */ public function testAuthenticateWhenPostChecksFails() { diff --git a/Tests/Core/Authentication/Provider/UserAuthenticationProviderTest.php b/Tests/Core/Authentication/Provider/UserAuthenticationProviderTest.php index 1b68531..1516a5f 100644 --- a/Tests/Core/Authentication/Provider/UserAuthenticationProviderTest.php +++ b/Tests/Core/Authentication/Provider/UserAuthenticationProviderTest.php @@ -33,7 +33,7 @@ class UserAuthenticationProviderTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\UsernameNotFoundException + * @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException */ public function testAuthenticateWhenUsernameIsNotFound() { @@ -47,7 +47,7 @@ class UserAuthenticationProviderTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\BadCredentialsException + * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException */ public function testAuthenticateWhenUsernameIsNotFoundAndHideIsTrue() { @@ -61,7 +61,7 @@ class UserAuthenticationProviderTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\AuthenticationServiceException + * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationServiceException */ public function testAuthenticateWhenProviderDoesNotReturnAnUserInterface() { @@ -75,7 +75,7 @@ class UserAuthenticationProviderTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\CredentialsExpiredException + * @expectedException \Symfony\Component\Security\Core\Exception\CredentialsExpiredException */ public function testAuthenticateWhenPreChecksFails() { @@ -95,7 +95,7 @@ class UserAuthenticationProviderTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\AccountExpiredException + * @expectedException \Symfony\Component\Security\Core\Exception\AccountExpiredException */ public function testAuthenticateWhenPostChecksFails() { @@ -115,7 +115,7 @@ class UserAuthenticationProviderTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\BadCredentialsException + * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException * @expectedExceptionMessage Bad credentials */ public function testAuthenticateWhenPostCheckAuthenticationFails() @@ -134,7 +134,7 @@ class UserAuthenticationProviderTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\BadCredentialsException + * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException * @expectedExceptionMessage Foo */ public function testAuthenticateWhenPostCheckAuthenticationFailsWithHideFalse() diff --git a/Tests/Core/Authentication/RememberMe/InMemoryTokenProviderTest.php b/Tests/Core/Authentication/RememberMe/InMemoryTokenProviderTest.php index 3944fb1..1739714 100644 --- a/Tests/Core/Authentication/RememberMe/InMemoryTokenProviderTest.php +++ b/Tests/Core/Authentication/RememberMe/InMemoryTokenProviderTest.php @@ -27,7 +27,7 @@ class InMemoryTokenProviderTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\TokenNotFoundException + * @expectedException \Symfony\Component\Security\Core\Exception\TokenNotFoundException */ public function testLoadTokenBySeriesThrowsNotFoundException() { @@ -49,7 +49,7 @@ class InMemoryTokenProviderTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\TokenNotFoundException + * @expectedException \Symfony\Component\Security\Core\Exception\TokenNotFoundException */ public function testDeleteToken() { diff --git a/Tests/Core/Encoder/BCryptPasswordEncoderTest.php b/Tests/Core/Encoder/BCryptPasswordEncoderTest.php new file mode 100644 index 0000000..bfaf5fc --- /dev/null +++ b/Tests/Core/Encoder/BCryptPasswordEncoderTest.php @@ -0,0 +1,112 @@ +<?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\Core\Encoder; + +use Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder; + +/** + * @author Elnur Abdurrakhimov <elnur@elnur.pro> + */ +class BCryptPasswordEncoderTest extends \PHPUnit_Framework_TestCase +{ + const PASSWORD = 'password'; + const BYTES = '0123456789abcdef'; + const VALID_COST = '04'; + + const SECURE_RANDOM_INTERFACE = 'Symfony\Component\Security\Core\Util\SecureRandomInterface'; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $secureRandom; + + protected function setUp() + { + $this->secureRandom = $this->getMock(self::SECURE_RANDOM_INTERFACE); + + $this->secureRandom + ->expects($this->any()) + ->method('nextBytes') + ->will($this->returnValue(self::BYTES)) + ; + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testCostBelowRange() + { + new BCryptPasswordEncoder($this->secureRandom, 3); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testCostAboveRange() + { + new BCryptPasswordEncoder($this->secureRandom, 32); + } + + public function testCostInRange() + { + for ($cost = 4; $cost <= 31; $cost++) { + new BCryptPasswordEncoder($this->secureRandom, $cost); + } + } + + public function testResultLength() + { + $encoder = new BCryptPasswordEncoder($this->secureRandom, self::VALID_COST); + $result = $encoder->encodePassword(self::PASSWORD, null); + $this->assertEquals(60, strlen($result)); + } + + public function testValidation() + { + $encoder = new BCryptPasswordEncoder($this->secureRandom, self::VALID_COST); + $result = $encoder->encodePassword(self::PASSWORD, null); + $this->assertTrue($encoder->isPasswordValid($result, self::PASSWORD, null)); + $this->assertFalse($encoder->isPasswordValid($result, 'anotherPassword', null)); + } + + public function testValidationKnownPassword() + { + $encoder = new BCryptPasswordEncoder($this->secureRandom, self::VALID_COST); + $prefix = '$'.(version_compare(phpversion(), '5.3.7', '>=') + ? '2y' : '2a').'$'; + + $encrypted = $prefix.'04$ABCDEFGHIJKLMNOPQRSTU.uTmwd4KMSHxbUsG7bng8x7YdA0PM1iq'; + $this->assertTrue($encoder->isPasswordValid($encrypted, self::PASSWORD, null)); + } + + public function testSecureRandomIsUsed() + { + if (function_exists('mcrypt_create_iv')) { + return; + } + + $this->secureRandom + ->expects($this->atLeastOnce()) + ->method('nextBytes') + ; + + $encoder = new BCryptPasswordEncoder($this->secureRandom, self::VALID_COST); + $result = $encoder->encodePassword(self::PASSWORD, null); + + $prefix = '$'.(version_compare(phpversion(), '5.3.7', '>=') + ? '2y' : '2a').'$'; + $salt = 'MDEyMzQ1Njc4OWFiY2RlZe'; + $expected = crypt(self::PASSWORD, $prefix . self::VALID_COST . '$' . $salt); + + $this->assertEquals($expected, $result); + } +} diff --git a/Tests/Core/Encoder/Pbkdf2PasswordEncoderTest.php b/Tests/Core/Encoder/Pbkdf2PasswordEncoderTest.php new file mode 100644 index 0000000..2c98543 --- /dev/null +++ b/Tests/Core/Encoder/Pbkdf2PasswordEncoderTest.php @@ -0,0 +1,45 @@ +<?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\Core\Encoder; + +use Symfony\Component\Security\Core\Encoder\Pbkdf2PasswordEncoder; + +class Pbkdf2PasswordEncoderTest extends \PHPUnit_Framework_TestCase +{ + public function testIsPasswordValid() + { + $encoder = new Pbkdf2PasswordEncoder('sha256', false, 1, 40); + + $this->assertTrue($encoder->isPasswordValid('c1232f10f62715fda06ae7c0a2037ca19b33cf103b727ba56d870c11f290a2ab106974c75607c8a3', 'password', '')); + } + + public function testEncodePassword() + { + $encoder = new Pbkdf2PasswordEncoder('sha256', false, 1, 40); + $this->assertSame('c1232f10f62715fda06ae7c0a2037ca19b33cf103b727ba56d870c11f290a2ab106974c75607c8a3', $encoder->encodePassword('password', '')); + + $encoder = new Pbkdf2PasswordEncoder('sha256', true, 1, 40); + $this->assertSame('wSMvEPYnFf2gaufAogN8oZszzxA7cnulbYcMEfKQoqsQaXTHVgfIow==', $encoder->encodePassword('password', '')); + + $encoder = new Pbkdf2PasswordEncoder('sha256', false, 2, 40); + $this->assertSame('8bc2f9167a81cdcfad1235cd9047f1136271c1f978fcfcb35e22dbeafa4634f6fd2214218ed63ebb', $encoder->encodePassword('password', '')); + } + + /** + * @expectedException LogicException + */ + public function testEncodePasswordAlgorithmDoesNotExist() + { + $encoder = new Pbkdf2PasswordEncoder('foobar'); + $encoder->encodePassword('password', ''); + } +} diff --git a/Tests/Core/SecurityContextTest.php b/Tests/Core/SecurityContextTest.php index 66a4b13..124ebf9 100644 --- a/Tests/Core/SecurityContextTest.php +++ b/Tests/Core/SecurityContextTest.php @@ -41,7 +41,7 @@ class SecurityContextTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException + * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException */ public function testVoteWithoutAuthenticationToken() { diff --git a/Tests/Core/User/AccountCheckerTest.php b/Tests/Core/User/AccountCheckerTest.php index 315e0d4..f28067f 100644 --- a/Tests/Core/User/AccountCheckerTest.php +++ b/Tests/Core/User/AccountCheckerTest.php @@ -33,7 +33,7 @@ class UserCheckerTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\CredentialsExpiredException + * @expectedException \Symfony\Component\Security\Core\Exception\CredentialsExpiredException */ public function testCheckPreAuthCredentialsExpired() { @@ -65,7 +65,7 @@ class UserCheckerTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\LockedException + * @expectedException \Symfony\Component\Security\Core\Exception\LockedException */ public function testCheckPostAuthAccountLocked() { @@ -78,7 +78,7 @@ class UserCheckerTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\DisabledException + * @expectedException \Symfony\Component\Security\Core\Exception\DisabledException */ public function testCheckPostAuthDisabled() { @@ -92,7 +92,7 @@ class UserCheckerTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\AccountExpiredException + * @expectedException \Symfony\Component\Security\Core\Exception\AccountExpiredException */ public function testCheckPostAuthAccountExpired() { diff --git a/Tests/Core/User/ChainUserProviderTest.php b/Tests/Core/User/ChainUserProviderTest.php index 5edbbed..0fddcd6 100644 --- a/Tests/Core/User/ChainUserProviderTest.php +++ b/Tests/Core/User/ChainUserProviderTest.php @@ -42,7 +42,7 @@ class ChainUserProviderTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\UsernameNotFoundException + * @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException */ public function testLoadUserByUsernameThrowsUsernameNotFoundException() { @@ -107,7 +107,7 @@ class ChainUserProviderTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\UnsupportedUserException + * @expectedException \Symfony\Component\Security\Core\Exception\UnsupportedUserException */ public function testRefreshUserThrowsUnsupportedUserException() { diff --git a/Tests/Core/User/InMemoryProviderTest.php b/Tests/Core/User/InMemoryProviderTest.php index 9230be4..5197a29 100644 --- a/Tests/Core/User/InMemoryProviderTest.php +++ b/Tests/Core/User/InMemoryProviderTest.php @@ -52,7 +52,7 @@ class InMemoryUserProviderTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\UsernameNotFoundException + * @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException */ public function testLoadUserByUsernameDoesNotExist() { diff --git a/Tests/Core/Util/ClassUtilsTest.php b/Tests/Core/Util/ClassUtilsTest.php index 16378a6..8359236 100644 --- a/Tests/Core/Util/ClassUtilsTest.php +++ b/Tests/Core/Util/ClassUtilsTest.php @@ -1,12 +1,21 @@ <?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\Core\Util { use Symfony\Component\Security\Core\Util\ClassUtils; class ClassUtilsTest extends \PHPUnit_Framework_TestCase { - static public function dataGetClass() + public static function dataGetClass() { return array( array('stdClass', 'stdClass'), diff --git a/Tests/Core/Util/SecureRandomTest.php b/Tests/Core/Util/SecureRandomTest.php new file mode 100755 index 0000000..c7ed016 --- /dev/null +++ b/Tests/Core/Util/SecureRandomTest.php @@ -0,0 +1,201 @@ +<?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\Core\Util; + +use Symfony\Component\Security\Core\Util\SecureRandom; + +class SecureRandomTest extends \PHPUnit_Framework_TestCase +{ + /** + * T1: Monobit test + * + * @dataProvider getSecureRandoms + */ + public function testMonobit($secureRandom) + { + $nbOnBits = substr_count($this->getBitSequence($secureRandom, 20000), '1'); + $this->assertTrue($nbOnBits > 9654 && $nbOnBits < 10346, 'Monobit test failed, number of turned on bits: '.$nbOnBits); + } + + /** + * T2: Chi-square test with 15 degrees of freedom (chi-Quadrat-Anpassungstest) + * + * @dataProvider getSecureRandoms + */ + public function testPoker($secureRandom) + { + $b = $this->getBitSequence($secureRandom, 20000); + $c = array(); + for ($i = 0; $i <= 15; $i++) { + $c[$i] = 0; + } + + for ($j = 1; $j <= 5000; $j++) { + $k = 4 * $j - 1; + $c[8 * $b[$k - 3] + 4 * $b[$k - 2] + 2 * $b[$k - 1] + $b[$k]] += 1; + } + + $f = 0; + for ($i = 0; $i <= 15; $i++) { + $f += $c[$i] * $c[$i]; + } + + $Y = 16/5000 * $f - 5000; + + $this->assertTrue($Y > 1.03 && $Y < 57.4, 'Poker test failed, Y = '.$Y); + } + + /** + * Run test + * + * @dataProvider getSecureRandoms + */ + public function testRun($secureRandom) + { + $b = $this->getBitSequence($secureRandom, 20000); + + $runs = array(); + for ($i = 1; $i <= 6; $i++) { + $runs[$i] = 0; + } + + $addRun = function($run) use (&$runs) { + if ($run > 6) { + $run = 6; + } + + $runs[$run] += 1; + }; + + $currentRun = 0; + $lastBit = null; + for ($i = 0; $i < 20000; $i++) { + if ($lastBit === $b[$i]) { + $currentRun += 1; + } else { + if ($currentRun > 0) { + $addRun($currentRun); + } + + $lastBit = $b[$i]; + $currentRun = 0; + } + } + if ($currentRun > 0) { + $addRun($currentRun); + } + + $this->assertTrue($runs[1] > 2267 && $runs[1] < 2733, 'Runs of length 1 outside of defined interval: '.$runs[1]); + $this->assertTrue($runs[2] > 1079 && $runs[2] < 1421, 'Runs of length 2 outside of defined interval: '.$runs[2]); + $this->assertTrue($runs[3] > 502 && $runs[3] < 748, 'Runs of length 3 outside of defined interval: '.$runs[3]); + $this->assertTrue($runs[4] > 233 && $runs[4] < 402, 'Runs of length 4 outside of defined interval: '.$runs[4]); + $this->assertTrue($runs[5] > 90 && $runs[5] < 223, 'Runs of length 5 outside of defined interval: '.$runs[5]); + $this->assertTrue($runs[6] > 90 && $runs[6] < 233, 'Runs of length 6 outside of defined interval: '.$runs[6]); + } + + /** + * Long-run test + * + * @dataProvider getSecureRandoms + */ + public function testLongRun($secureRandom) + { + $b = $this->getBitSequence($secureRandom, 20000); + + $longestRun = 0; + $currentRun = $lastBit = null; + for ($i = 0; $i < 20000; $i++) { + if ($lastBit === $b[$i]) { + $currentRun += 1; + } else { + if ($currentRun > $longestRun) { + $longestRun = $currentRun; + } + $lastBit = $b[$i]; + $currentRun = 0; + } + } + if ($currentRun > $longestRun) { + $longestRun = $currentRun; + } + + $this->assertTrue($longestRun < 34, 'Failed longest run test: '.$longestRun); + } + + /** + * Serial Correlation (Autokorrelationstest) + * + * @dataProvider getSecureRandoms + */ + public function testSerialCorrelation($secureRandom) + { + $shift = rand(1, 5000); + $b = $this->getBitSequence($secureRandom, 20000); + + $Z = 0; + for ($i = 0; $i < 5000; $i++) { + $Z += $b[$i] === $b[$i + $shift] ? 1 : 0; + } + + $this->assertTrue($Z > 2326 && $Z < 2674, 'Failed serial correlation test: '.$Z); + } + + public function getSecureRandoms() + { + $secureRandoms = array(); + + // only add if openssl is indeed present + $secureRandom = new SecureRandom(); + if ($this->hasOpenSsl($secureRandom)) { + $secureRandoms[] = array($secureRandom); + } + + // no-openssl with custom seed provider + $secureRandom = new SecureRandom(sys_get_temp_dir().'/_sf2.seed'); + $this->disableOpenSsl($secureRandom); + $secureRandoms[] = array($secureRandom); + + return $secureRandoms; + } + + protected function disableOpenSsl($secureRandom) + { + $ref = new \ReflectionProperty($secureRandom, 'useOpenSsl'); + $ref->setAccessible(true); + $ref->setValue($secureRandom, false); + $ref->setAccessible(false); + } + + protected function hasOpenSsl($secureRandom) + { + $ref = new \ReflectionProperty($secureRandom, 'useOpenSsl'); + $ref->setAccessible(true); + + $ret = $ref->getValue($secureRandom); + + $ref->setAccessible(false); + + return $ret; + } + + private function getBitSequence($secureRandom, $length) + { + $bitSequence = ''; + for ($i = 0; $i < $length; $i += 40) { + $value = unpack('H*', $secureRandom->nextBytes(5)); + $value = str_pad(base_convert($value[1], 16, 2), 40, '0', STR_PAD_LEFT); + $bitSequence .= $value; + } + + return substr($bitSequence, 0, $length); + } +} diff --git a/Tests/Core/Util/StringUtilsTest.php b/Tests/Core/Util/StringUtilsTest.php new file mode 100755 index 0000000..aac4139 --- /dev/null +++ b/Tests/Core/Util/StringUtilsTest.php @@ -0,0 +1,23 @@ +<?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\Core\Util; + +use Symfony\Component\Security\Core\Util\StringUtils; + +class StringUtilsTest extends \PHPUnit_Framework_TestCase +{ + public function testEquals() + { + $this->assertTrue(StringUtils::equals('password', 'password')); + $this->assertFalse(StringUtils::equals('password', 'foo')); + } +} diff --git a/Tests/Core/Validator/Constraints/UserPasswordValidatorTest.php b/Tests/Core/Validator/Constraints/UserPasswordValidatorTest.php new file mode 100644 index 0000000..c3a8370 --- /dev/null +++ b/Tests/Core/Validator/Constraints/UserPasswordValidatorTest.php @@ -0,0 +1,161 @@ +<?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\Core\Validator\Constraints; + +use Symfony\Component\Security\Core\Validator\Constraints\UserPassword; +use Symfony\Component\Security\Core\Validator\Constraints\UserPasswordValidator; + +class UserPasswordValidatorTest extends \PHPUnit_Framework_TestCase +{ + const PASSWORD_VALID = true; + const PASSWORD_INVALID = false; + + protected $context; + + protected function setUp() + { + if (false === class_exists('Symfony\Component\Validator\Validator')) { + $this->markTestSkipped('The Validator component is required for this test.'); + } + + $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); + } + + protected function tearDown() + { + $this->context = null; + } + + public function testPasswordIsValid() + { + $user = $this->createUser(); + $securityContext = $this->createSecurityContext($user); + + $encoder = $this->createPasswordEncoder(static::PASSWORD_VALID); + $encoderFactory = $this->createEncoderFactory($encoder); + + $validator = new UserPasswordValidator($securityContext, $encoderFactory); + $validator->initialize($this->context); + + $this + ->context + ->expects($this->never()) + ->method('addViolation') + ; + + $validator->validate('secret', new UserPassword()); + } + + public function testPasswordIsNotValid() + { + $user = $this->createUser(); + $securityContext = $this->createSecurityContext($user); + + $encoder = $this->createPasswordEncoder(static::PASSWORD_INVALID); + $encoderFactory = $this->createEncoderFactory($encoder); + + $validator = new UserPasswordValidator($securityContext, $encoderFactory); + $validator->initialize($this->context); + + $this + ->context + ->expects($this->once()) + ->method('addViolation') + ; + + $validator->validate('secret', new UserPassword()); + } + + public function testUserIsNotValid() + { + $this->setExpectedException('Symfony\Component\Validator\Exception\ConstraintDefinitionException'); + + $user = $this->getMock('Foo\Bar\User'); + $encoderFactory = $this->getMock('Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface'); + $securityContext = $this->createSecurityContext($user); + + $validator = new UserPasswordValidator($securityContext, $encoderFactory); + $validator->initialize($this->context); + $validator->validate('secret', new UserPassword()); + } + + protected function createUser() + { + $mock = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); + + $mock + ->expects($this->once()) + ->method('getPassword') + ->will($this->returnValue('s3Cr3t')) + ; + + $mock + ->expects($this->once()) + ->method('getSalt') + ->will($this->returnValue('^S4lt$')) + ; + + return $mock; + } + + protected function createPasswordEncoder($isPasswordValid = true) + { + $mock = $this->getMock('Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface'); + + $mock + ->expects($this->once()) + ->method('isPasswordValid') + ->will($this->returnValue($isPasswordValid)) + ; + + return $mock; + } + + protected function createEncoderFactory($encoder = null) + { + $mock = $this->getMock('Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface'); + + $mock + ->expects($this->once()) + ->method('getEncoder') + ->will($this->returnValue($encoder)) + ; + + return $mock; + } + + protected function createSecurityContext($user = null) + { + $token = $this->createAuthenticationToken($user); + + $mock = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); + $mock + ->expects($this->once()) + ->method('getToken') + ->will($this->returnValue($token)) + ; + + return $mock; + } + + protected function createAuthenticationToken($user = null) + { + $mock = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); + $mock + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($user)) + ; + + return $mock; + } +} 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/EntryPoint/FormAuthenticationEntryPointTest.php b/Tests/Http/EntryPoint/FormAuthenticationEntryPointTest.php index 2e72340..1cf2c2d 100644 --- a/Tests/Http/EntryPoint/FormAuthenticationEntryPointTest.php +++ b/Tests/Http/EntryPoint/FormAuthenticationEntryPointTest.php @@ -64,7 +64,7 @@ class FormAuthenticationEntryPointTest extends \PHPUnit_Framework_TestCase $httpKernel ->expects($this->once()) ->method('handle') - ->with($this->equalTo($request), $this->equalTo(HttpKernelInterface::SUB_REQUEST)) + ->with($this->equalTo($subRequest), $this->equalTo(HttpKernelInterface::SUB_REQUEST)) ->will($this->returnValue($response)) ; diff --git a/Tests/Http/Firewall/AccessListenerTest.php b/Tests/Http/Firewall/AccessListenerTest.php index e3ffbfc..53ab350 100644 --- a/Tests/Http/Firewall/AccessListenerTest.php +++ b/Tests/Http/Firewall/AccessListenerTest.php @@ -31,7 +31,7 @@ class AccessListenerTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\AccessDeniedException + * @expectedException \Symfony\Component\Security\Core\Exception\AccessDeniedException */ public function testHandleWhenTheAccessDecisionManagerDecidesToRefuseAccess() { @@ -198,7 +198,7 @@ class AccessListenerTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException + * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException */ public function testHandleWhenTheSecurityContextHasNoToken() { diff --git a/Tests/Http/Firewall/ContextListenerTest.php b/Tests/Http/Firewall/ContextListenerTest.php index 646ed23..ffe6195 100644 --- a/Tests/Http/Firewall/ContextListenerTest.php +++ b/Tests/Http/Firewall/ContextListenerTest.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Test\Component\Security\Http\Firewall; +namespace Symfony\Component\Security\Tests\Http\Firewall; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -82,17 +82,30 @@ class ContextListenerTest extends \PHPUnit_Framework_TestCase $this->assertFalse($session->has('_security_session')); } - protected function runSessionOnKernelResponse($newToken, $original = null) + public function testOnKernelResponseWithoutSession() { + $this->securityContext->setToken(new UsernamePasswordToken('test1', 'pass1', 'phpunit')); + $request = new Request(); $session = new Session(new MockArraySessionStorage()); + $request->setSession($session); - if ($original !== null) { - $session->set('_security_session', $original); - } + $event = new FilterResponseEvent( + $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'), + $request, + HttpKernelInterface::MASTER_REQUEST, + new Response() + ); - $this->securityContext->setToken($newToken); + $listener = new ContextListener($this->securityContext, array(), 'session'); + $listener->onKernelResponse($event); + $this->assertTrue($session->isStarted()); + } + + public function testOnKernelResponseWithoutSessionNorToken() + { $request = new Request(); + $session = new Session(new MockArraySessionStorage()); $request->setSession($session); $event = new FilterResponseEvent( @@ -105,13 +118,65 @@ class ContextListenerTest extends \PHPUnit_Framework_TestCase $listener = new ContextListener($this->securityContext, array(), 'session'); $listener->onKernelResponse($event); - return $session; + $this->assertFalse($session->isStarted()); } - public function testOnKernelResponseWithoutSession() + /** + * @dataProvider provideInvalidToken + */ + public function testInvalidTokenInSession($token) { - $this->securityContext->setToken(new UsernamePasswordToken('test1', 'pass1', 'phpunit')); + $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); + $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent') + ->disableOriginalConstructor() + ->getMock(); + $request = $this->getMock('Symfony\Component\HttpFoundation\Request'); + $session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\Session') + ->disableOriginalConstructor() + ->getMock(); + + $event->expects($this->any()) + ->method('getRequest') + ->will($this->returnValue($request)); + $request->expects($this->any()) + ->method('hasPreviousSession') + ->will($this->returnValue(true)); + $request->expects($this->any()) + ->method('getSession') + ->will($this->returnValue($session)); + $session->expects($this->any()) + ->method('get') + ->with('_security_key123') + ->will($this->returnValue(serialize($token))); + $context->expects($this->once()) + ->method('setToken') + ->with(null); + + $listener = new ContextListener($context, array(), 'key123'); + $listener->handle($event); + } + + public function provideInvalidToken() + { + return array( + array(new \__PHP_Incomplete_Class()), + array(null), + ); + } + + protected function runSessionOnKernelResponse($newToken, $original = null) + { + $session = new Session(new MockArraySessionStorage()); + + if ($original !== null) { + $session->set('_security_session', $original); + } + + $this->securityContext->setToken($newToken); + $request = new Request(); + $request->setSession($session); + $request->cookies->set('MOCKSESSID', true); $event = new FilterResponseEvent( $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'), @@ -123,6 +188,5 @@ class ContextListenerTest extends \PHPUnit_Framework_TestCase $listener = new ContextListener($this->securityContext, array(), 'session'); $listener->onKernelResponse($event); - $this->assertFalse($request->hasSession()); - } -} + return $session; + }} 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/Firewall/LogoutListenerTest.php b/Tests/Http/Firewall/LogoutListenerTest.php index 6ffeed9..ba94b6e 100644 --- a/Tests/Http/Firewall/LogoutListenerTest.php +++ b/Tests/Http/Firewall/LogoutListenerTest.php @@ -103,7 +103,9 @@ class LogoutListenerTest extends \PHPUnit_Framework_TestCase public function testHandleMatchedPathWithoutSuccessHandlerAndCsrfValidation() { - list($listener, $context, $httpUtils, $options) = $this->getListener(); + $successHandler = $this->getSuccessHandler(); + + list($listener, $context, $httpUtils, $options) = $this->getListener($successHandler); list($event, $request) = $this->getGetResponseEvent(); @@ -112,9 +114,9 @@ class LogoutListenerTest extends \PHPUnit_Framework_TestCase ->with($request, $options['logout_path']) ->will($this->returnValue(true)); - $httpUtils->expects($this->once()) - ->method('createRedirectResponse') - ->with($request, $options['target_url']) + $successHandler->expects($this->once()) + ->method('onLogoutSuccess') + ->with($request) ->will($this->returnValue($response = new Response())); $context->expects($this->once()) @@ -164,7 +166,7 @@ class LogoutListenerTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Security\Core\Exception\LogoutException + * @expectedException \Symfony\Component\Security\Core\Exception\LogoutException */ public function testCsrfValidationFails() { @@ -231,13 +233,13 @@ class LogoutListenerTest extends \PHPUnit_Framework_TestCase $listener = new LogoutListener( $context = $this->getContext(), $httpUtils = $this->getHttpUtils(), + $successHandler ?: $this->getSuccessHandler(), $options = array( 'csrf_parameter' => '_csrf_token', 'intention' => 'logout', 'logout_path' => '/logout', 'target_url' => '/', ), - $successHandler, $csrfProvider ); diff --git a/Tests/Http/Firewall/RememberMeListenerTest.php b/Tests/Http/Firewall/RememberMeListenerTest.php index 5f31273..8ad4c55 100644 --- a/Tests/Http/Firewall/RememberMeListenerTest.php +++ b/Tests/Http/Firewall/RememberMeListenerTest.php @@ -177,7 +177,7 @@ class RememberMeListenerTest extends \PHPUnit_Framework_TestCase protected function getLogger() { - return $this->getMock('Symfony\Component\HttpKernel\Log\LoggerInterface'); + return $this->getMock('Psr\Log\LoggerInterface'); } protected function getManager() diff --git a/Tests/Http/HttpUtilsTest.php b/Tests/Http/HttpUtilsTest.php index a30051f..bf078da 100644 --- a/Tests/Http/HttpUtilsTest.php +++ b/Tests/Http/HttpUtilsTest.php @@ -97,6 +97,11 @@ class HttpUtilsTest extends \PHPUnit_Framework_TestCase $this->assertTrue($utils->checkRequestPath($this->getRequest(), '/')); $this->assertFalse($utils->checkRequestPath($this->getRequest(), '/foo')); + $this->assertTrue($utils->checkRequestPath($this->getRequest('/foo%20bar'), '/foo bar')); + // Plus must not decoded to space + $this->assertTrue($utils->checkRequestPath($this->getRequest('/foo+bar'), '/foo+bar')); + // Checking unicode + $this->assertTrue($utils->checkRequestPath($this->getRequest(urlencode('/вход')), '/вход')); $urlMatcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface'); $urlMatcher @@ -132,13 +137,25 @@ class HttpUtilsTest extends \PHPUnit_Framework_TestCase $utils->checkRequestPath($this->getRequest(), 'foobar'); } - private function getUrlGenerator() + public function testGenerateUriRemovesQueryString() + { + $method = new \ReflectionMethod('Symfony\Component\Security\Http\HttpUtils', 'generateUri'); + $method->setAccessible(true); + + $utils = new HttpUtils($this->getUrlGenerator()); + $this->assertEquals('/foo/bar', $method->invoke($utils, new Request(), 'route_name')); + + $utils = new HttpUtils($this->getUrlGenerator('/foo/bar?param=value')); + $this->assertEquals('/foo/bar', $method->invoke($utils, new Request(), 'route_name')); + } + + private function getUrlGenerator($generatedUrl = '/foo/bar') { $urlGenerator = $this->getMock('Symfony\Component\Routing\Generator\UrlGeneratorInterface'); $urlGenerator ->expects($this->any()) ->method('generate') - ->will($this->returnValue('/foo/bar')) + ->will($this->returnValue($generatedUrl)) ; return $urlGenerator; 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/PersistentTokenBasedRememberMeServicesTest.php b/Tests/Http/RememberMe/PersistentTokenBasedRememberMeServicesTest.php index 3b3691d..7fc3021 100644 --- a/Tests/Http/RememberMe/PersistentTokenBasedRememberMeServicesTest.php +++ b/Tests/Http/RememberMe/PersistentTokenBasedRememberMeServicesTest.php @@ -22,6 +22,7 @@ use Symfony\Component\HttpFoundation\ResponseHeaderBag; use Symfony\Component\Security\Http\RememberMe\PersistentTokenBasedRememberMeServices; use Symfony\Component\Security\Core\Exception\TokenNotFoundException; use Symfony\Component\Security\Core\Exception\CookieTheftException; +use Symfony\Component\Security\Core\Util\SecureRandom; class PersistentTokenBasedRememberMeServicesTest extends \PHPUnit_Framework_TestCase { @@ -318,7 +319,7 @@ class PersistentTokenBasedRememberMeServicesTest extends \PHPUnit_Framework_Test $userProvider = $this->getProvider(); } - return new PersistentTokenBasedRememberMeServices(array($userProvider), 'fookey', 'fookey', $options, $logger); + return new PersistentTokenBasedRememberMeServices(array($userProvider), 'fookey', 'fookey', $options, $logger, new SecureRandom(sys_get_temp_dir().'/_sf2.seed')); } protected function getProvider() 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/composer.json b/composer.json index 17b3e15..dd4eecf 100644 --- a/composer.json +++ b/composer.json @@ -17,32 +17,34 @@ ], "require": { "php": ">=5.3.3", - "symfony/event-dispatcher": "2.1.*", - "symfony/http-foundation": "2.1.*", - "symfony/http-kernel": "2.1.*" + "symfony/event-dispatcher": "~2.1", + "symfony/http-foundation": ">=2.1,<2.4-dev", + "symfony/http-kernel": ">=2.1,<=2.3-dev" }, "require-dev": { - "symfony/form": "2.1.*", - "symfony/routing": "2.1.*", - "symfony/validator": "2.1.*", - "doctrine/common": ">=2.2,<2.4-dev", - "doctrine/dbal": ">=2.2,<2.4-dev" + "symfony/form": "~2.0", + "symfony/routing": ">=2.2,<2.4-dev", + "symfony/validator": ">=2.2,<2.4-dev", + "doctrine/common": "~2.2", + "doctrine/dbal": "~2.2", + "psr/log": "~1.0" }, "suggest": { - "symfony/class-loader": "self.version", - "symfony/finder": "self.version", - "symfony/form": "self.version", - "symfony/validator": "self.version", - "symfony/routing": "self.version", + "symfony/class-loader": "2.2.*", + "symfony/finder": "2.2.*", + "symfony/form": "2.2.*", + "symfony/validator": "2.2.*", + "symfony/routing": "2.2.*", "doctrine/dbal": "to use the built-in ACL implementation" }, "autoload": { - "psr-0": { "Symfony\\Component\\Security": "" } + "psr-0": { "Symfony\\Component\\Security\\": "" } }, "target-dir": "Symfony/Component/Security", + "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "2.1-dev" + "dev-master": "2.3-dev" } } } 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"> |