diff options
author | Fabien Potencier <fabien.potencier@gmail.com> | 2011-05-30 14:28:54 +0200 |
---|---|---|
committer | Fabien Potencier <fabien.potencier@gmail.com> | 2011-05-30 14:28:54 +0200 |
commit | 2798d3b4b0f385df4547aaceedf8eac93111520c (patch) | |
tree | fd0237dd131869bf5d61fe33c2a564a8c6efd081 | |
parent | 127c65198b16c3f7a48fa5d19a315b3e34527178 (diff) | |
parent | 2acac06004a24699d9a5c257d143446272b88d38 (diff) | |
download | symfony-security-2798d3b4b0f385df4547aaceedf8eac93111520c.zip symfony-security-2798d3b4b0f385df4547aaceedf8eac93111520c.tar.gz symfony-security-2798d3b4b0f385df4547aaceedf8eac93111520c.tar.bz2 |
merged origin/master
-rw-r--r-- | Acl/Dbal/MutableAclProvider.php | 4 | ||||
-rw-r--r-- | Acl/Domain/ObjectIdentity.php | 2 | ||||
-rw-r--r-- | Acl/Domain/RoleSecurityIdentity.php | 2 | ||||
-rw-r--r-- | Acl/Domain/UserSecurityIdentity.php | 4 | ||||
-rw-r--r-- | Acl/Permission/BasicPermissionMap.php | 4 | ||||
-rw-r--r-- | Acl/Permission/PermissionMapInterface.php | 5 | ||||
-rw-r--r-- | Acl/Voter/AclVoter.php | 63 | ||||
-rw-r--r-- | Core/Exception/SessionUnavailableException.php | 27 | ||||
-rw-r--r-- | Http/Firewall/AbstractAuthenticationListener.php | 11 | ||||
-rw-r--r-- | Http/Firewall/UsernamePasswordFormAuthenticationListener.php | 2 |
10 files changed, 79 insertions, 45 deletions
diff --git a/Acl/Dbal/MutableAclProvider.php b/Acl/Dbal/MutableAclProvider.php index 62667c8..9050cf8 100644 --- a/Acl/Dbal/MutableAclProvider.php +++ b/Acl/Dbal/MutableAclProvider.php @@ -246,6 +246,10 @@ class MutableAclProvider extends AclProvider implements MutableAclProviderInterf } $this->regenerateAncestorRelations($acl); + $childAcls = $this->findAcls($this->findChildren($acl->getObjectIdentity(), false)); + foreach ($childAcls as $childOid) { + $this->regenerateAncestorRelations($childAcls[$childOid]); + } } // this includes only updates of existing ACEs, but neither the creation, nor diff --git a/Acl/Domain/ObjectIdentity.php b/Acl/Domain/ObjectIdentity.php index f55f8a5..e691689 100644 --- a/Acl/Domain/ObjectIdentity.php +++ b/Acl/Domain/ObjectIdentity.php @@ -20,7 +20,7 @@ use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface; * * @author Johannes M. Schmitt <schmittjoh@gmail.com> */ -class ObjectIdentity implements ObjectIdentityInterface +final class ObjectIdentity implements ObjectIdentityInterface { private $identifier; private $type; diff --git a/Acl/Domain/RoleSecurityIdentity.php b/Acl/Domain/RoleSecurityIdentity.php index d3694e6..67ad59e 100644 --- a/Acl/Domain/RoleSecurityIdentity.php +++ b/Acl/Domain/RoleSecurityIdentity.php @@ -19,7 +19,7 @@ use Symfony\Component\Security\Core\Role\Role; * * @author Johannes M. Schmitt <schmittjoh@gmail.com> */ -class RoleSecurityIdentity implements SecurityIdentityInterface +final class RoleSecurityIdentity implements SecurityIdentityInterface { private $role; diff --git a/Acl/Domain/UserSecurityIdentity.php b/Acl/Domain/UserSecurityIdentity.php index ac63080..d81eaaf 100644 --- a/Acl/Domain/UserSecurityIdentity.php +++ b/Acl/Domain/UserSecurityIdentity.php @@ -20,7 +20,7 @@ use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface; * * @author Johannes M. Schmitt <schmittjoh@gmail.com> */ -class UserSecurityIdentity implements SecurityIdentityInterface +final class UserSecurityIdentity implements SecurityIdentityInterface { private $username; private $class; @@ -40,7 +40,7 @@ class UserSecurityIdentity implements SecurityIdentityInterface throw new \InvalidArgumentException('$class must not be empty.'); } - $this->username = $username; + $this->username = (string) $username; $this->class = $class; } diff --git a/Acl/Permission/BasicPermissionMap.php b/Acl/Permission/BasicPermissionMap.php index 18006ff..dcf49df 100644 --- a/Acl/Permission/BasicPermissionMap.php +++ b/Acl/Permission/BasicPermissionMap.php @@ -84,10 +84,10 @@ class BasicPermissionMap implements PermissionMapInterface /** * {@inheritDoc} */ - public function getMasks($permission) + public function getMasks($permission, $object) { if (!isset($this->map[$permission])) { - throw new \InvalidArgumentException(sprintf('The permission "%s" is not supported by this implementation.', $permission)); + return null; } return $this->map[$permission]; diff --git a/Acl/Permission/PermissionMapInterface.php b/Acl/Permission/PermissionMapInterface.php index bc4ca08..fb41cc9 100644 --- a/Acl/Permission/PermissionMapInterface.php +++ b/Acl/Permission/PermissionMapInterface.php @@ -25,9 +25,10 @@ interface PermissionMapInterface * these bitmasks. * * @param string $permission - * @return array + * @param object $object + * @return array may return null if permission/object combination is not supported */ - function getMasks($permission); + function getMasks($permission, $object); /** * Whether this map contains the given permission diff --git a/Acl/Voter/AclVoter.php b/Acl/Voter/AclVoter.php index 7bd8610..0e1567d 100644 --- a/Acl/Voter/AclVoter.php +++ b/Acl/Voter/AclVoter.php @@ -57,58 +57,45 @@ class AclVoter implements VoterInterface public function vote(TokenInterface $token, $object, array $attributes) { - $firstCall = true; foreach ($attributes as $attribute) { - if (!$this->supportsAttribute($attribute)) { + if (null === $masks = $this->permissionMap->getMasks($attribute, $object)) { continue; } - if ($firstCall) { - $firstCall = false; - - if (null === $object) { - if (null !== $this->logger) { - $this->logger->debug(sprintf('Object identity unavailable. Voting to %s', $this->allowIfObjectIdentityUnavailable? 'grant access' : 'abstain')); - } - - return $this->allowIfObjectIdentityUnavailable ? self::ACCESS_GRANTED : self::ACCESS_ABSTAIN; - } else if ($object instanceof FieldVote) { - $field = $object->getField(); - $object = $object->getDomainObject(); - } else { - $field = null; + if (null === $object) { + if (null !== $this->logger) { + $this->logger->debug(sprintf('Object identity unavailable. Voting to %s', $this->allowIfObjectIdentityUnavailable? 'grant access' : 'abstain')); } - if ($object instanceof ObjectIdentityInterface) { - $oid = $object; - } else if (null === $oid = $this->objectIdentityRetrievalStrategy->getObjectIdentity($object)) { - if (null !== $this->logger) { - $this->logger->debug(sprintf('Object identity unavailable. Voting to %s', $this->allowIfObjectIdentityUnavailable? 'grant access' : 'abstain')); - } + return $this->allowIfObjectIdentityUnavailable ? self::ACCESS_GRANTED : self::ACCESS_ABSTAIN; + } else if ($object instanceof FieldVote) { + $field = $object->getField(); + $object = $object->getDomainObject(); + } else { + $field = null; + } - return $this->allowIfObjectIdentityUnavailable ? self::ACCESS_GRANTED : self::ACCESS_ABSTAIN; + if ($object instanceof ObjectIdentityInterface) { + $oid = $object; + } else if (null === $oid = $this->objectIdentityRetrievalStrategy->getObjectIdentity($object)) { + if (null !== $this->logger) { + $this->logger->debug(sprintf('Object identity unavailable. Voting to %s', $this->allowIfObjectIdentityUnavailable? 'grant access' : 'abstain')); } - $sids = $this->securityIdentityRetrievalStrategy->getSecurityIdentities($token); - try { - $acl = $this->aclProvider->findAcl($oid, $sids); - } catch (AclNotFoundException $noAcl) { - if (null !== $this->logger) { - $this->logger->debug('No ACL found for the object identity. Voting to deny access.'); - } - - return self::ACCESS_DENIED; - } + return $this->allowIfObjectIdentityUnavailable ? self::ACCESS_GRANTED : self::ACCESS_ABSTAIN; } + $sids = $this->securityIdentityRetrievalStrategy->getSecurityIdentities($token); try { - if (null === $field && $acl->isGranted($this->permissionMap->getMasks($attribute), $sids, false)) { + $acl = $this->aclProvider->findAcl($oid, $sids); + + if (null === $field && $acl->isGranted($masks, $sids, false)) { if (null !== $this->logger) { $this->logger->debug('ACL found, permission granted. Voting to grant access'); } return self::ACCESS_GRANTED; - } else if (null !== $field && $acl->isFieldGranted($field, $this->permissionMap->getMasks($attribute), $sids, false)) { + } else if (null !== $field && $acl->isFieldGranted($field, $masks, $sids, false)) { if (null !== $this->logger) { $this->logger->debug('ACL found, permission granted. Voting to grant access'); } @@ -121,6 +108,12 @@ class AclVoter implements VoterInterface } return self::ACCESS_DENIED; + } catch (AclNotFoundException $noAcl) { + if (null !== $this->logger) { + $this->logger->debug('No ACL found for the object identity. Voting to deny access.'); + } + + return self::ACCESS_DENIED; } catch (NoAceFoundException $noAce) { if (null !== $this->logger) { $this->logger->debug('ACL found, no ACE applicable. Voting to deny access.'); diff --git a/Core/Exception/SessionUnavailableException.php b/Core/Exception/SessionUnavailableException.php new file mode 100644 index 0000000..a00c897 --- /dev/null +++ b/Core/Exception/SessionUnavailableException.php @@ -0,0 +1,27 @@ +<?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\Exception; + +/** + * This exception is thrown when no session is available. + * + * Possible reasons for this are: + * + * a) The session timed-out because the user waited too long. + * b) The user has disabled cookies, and a new session is started on each + * request. + * + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +class SessionUnavailableException extends AuthenticationException +{ +}
\ No newline at end of file diff --git a/Http/Firewall/AbstractAuthenticationListener.php b/Http/Firewall/AbstractAuthenticationListener.php index e2e1ed6..f2be84e 100644 --- a/Http/Firewall/AbstractAuthenticationListener.php +++ b/Http/Firewall/AbstractAuthenticationListener.php @@ -18,6 +18,7 @@ use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface; 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 Symfony\Component\HttpKernel\CoreEvents; @@ -128,6 +129,14 @@ abstract class AbstractAuthenticationListener implements ListenerInterface return; } + if (!$request->hasSession()) { + throw new \RuntimeException('This authentication method requires a session.'); + } + + if (!$request->hasPreviousSession()) { + throw new SessionUnavailableException('Your session has timed-out, or you have disabled cookies.'); + } + if ($returnValue instanceof TokenInterface) { $this->sessionStrategy->onAuthentication($request, $returnValue); @@ -227,7 +236,7 @@ abstract class AbstractAuthenticationListener implements ListenerInterface if (null !== $this->successHandler) { $response = $this->successHandler->onAuthenticationSuccess($request, $token); } else { - $path = $this->determineTargetUrl($request); + $path = strtr($this->determineTargetUrl($request), '{_locale}', $session->getLocale()); $response = new RedirectResponse(0 !== strpos($path, 'http') ? $request->getUriForPath($path) : $path, 302); } diff --git a/Http/Firewall/UsernamePasswordFormAuthenticationListener.php b/Http/Firewall/UsernamePasswordFormAuthenticationListener.php index 51546c0..e76b1bf 100644 --- a/Http/Firewall/UsernamePasswordFormAuthenticationListener.php +++ b/Http/Firewall/UsernamePasswordFormAuthenticationListener.php @@ -63,7 +63,7 @@ class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationL } if (null !== $this->csrfProvider) { - $csrfToken = $request->get($this->options['csrf_parameter']); + $csrfToken = $request->get($this->options['csrf_parameter'], null, true); if (false === $this->csrfProvider->isCsrfTokenValid($this->options['intention'], $csrfToken)) { throw new InvalidCsrfTokenException('Invalid CSRF token.'); |