Skip to content

Commit

Permalink
added authentication trust resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
schmittjoh authored and fabpot committed Dec 12, 2010
1 parent 763bba9 commit abe8047
Show file tree
Hide file tree
Showing 10 changed files with 321 additions and 22 deletions.
Expand Up @@ -450,7 +450,7 @@ protected function createExceptionListener($container, $id, $defaultEntryPoint)
$exceptionListenerId = 'security.exception_listener.'.$id;
$listener = $container->setDefinition($exceptionListenerId, clone $container->getDefinition('security.exception_listener'));
$arguments = $listener->getArguments();
$arguments[1] = null === $defaultEntryPoint ? null : new Reference($defaultEntryPoint);
$arguments[2] = null === $defaultEntryPoint ? null : new Reference($defaultEntryPoint);
$listener->setArguments($arguments);

return $exceptionListenerId;
Expand Down
10 changes: 10 additions & 0 deletions src/Symfony/Bundle/FrameworkBundle/Resources/config/security.xml
Expand Up @@ -16,6 +16,10 @@

<parameter key="security.user.provider.in_memory.class">Symfony\Component\Security\User\InMemoryUserProvider</parameter>

<parameter key="security.authentication.trust_resolver.class">Symfony\Component\Security\Authentication\AuthenticationTrustResolver</parameter>
<parameter key="security.authentication.trust_resolver.anonymous_class">Symfony\Component\Security\Authentication\Token\AnonymousToken</parameter>
<parameter key="security.authentication.trust_resolver.rememberme_class">Symfony\Component\Security\Authentication\Token\RememberMeToken</parameter>

<parameter key="security.authentication.provider.dao.class">Symfony\Component\Security\Authentication\Provider\DaoAuthenticationProvider</parameter>
<parameter key="security.authentication.provider.pre_authenticated.class">Symfony\Component\Security\Authentication\Provider\PreAuthenticatedAuthenticationProvider</parameter>

Expand Down Expand Up @@ -101,6 +105,11 @@
<argument type="service" id="logger" on-invalid="null" />
</service>

<service id="security.authentication.trust_resolver" class="%security.authentication.trust_resolver.class%">
<argument>%security.authentication.trust_resolver.anonymous_class%</argument>
<argument>%security.authentication.trust_resolver.rememberme_class%</argument>
</service>

<service id="security.authentication.retry_entry_point" class="%security.authentication.retry_entry_point.class%" />

<service id="security.authentication.form_entry_point" class="%security.authentication.form_entry_point.class%">
Expand Down Expand Up @@ -132,6 +141,7 @@
<tag name="security.voter" />
</service>
<service id="security.access.authenticated_voter" class="%security.access.authenticated_voter.class%">
<argument type="service" id="security.authentication.trust_resolver" />
<tag name="security.voter" />
</service>
<service id="security.access.role_hierarchy_voter" class="%security.access.role_hierarchy_voter.class%">
Expand Down
Expand Up @@ -62,6 +62,7 @@

<service id="security.exception_listener" class="%security.exception_listener.class%">
<argument type="service" id="security.context" />
<argument type="service" id="security.authentication.trust_resolver" />
<argument type="service" id="security.authentication.entry_point" on-invalid="null" />
<argument>%security.access_denied.url%</argument>
<argument type="service" id="logger" on-invalid="null" />
Expand Down
Expand Up @@ -3,6 +3,7 @@
namespace Symfony\Component\HttpKernel\Security\Firewall;

use Symfony\Component\Security\SecurityContext;
use Symfony\Component\Security\Authentication\AuthenticationTrustResolverInterface;
use Symfony\Component\Security\Authentication\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;
Expand Down Expand Up @@ -33,13 +34,15 @@ class ExceptionListener implements ListenerInterface
{
protected $context;
protected $authenticationEntryPoint;
protected $authenticationTrustResolver;
protected $errorPage;
protected $logger;

public function __construct(SecurityContext $context, AuthenticationEntryPointInterface $authenticationEntryPoint = null, $errorPage = null, LoggerInterface $logger = null)
public function __construct(SecurityContext $context, AuthenticationTrustResolverInterface $trustResolver, AuthenticationEntryPointInterface $authenticationEntryPoint = null, $errorPage = null, LoggerInterface $logger = null)
{
$this->context = $context;
$this->authenticationEntryPoint = $authenticationEntryPoint;
$this->authenticationTrustResolver = $trustResolver;
$this->errorPage = $errorPage;
$this->logger = $logger;
}
Expand Down Expand Up @@ -87,9 +90,9 @@ public function handleException(Event $event)
}
} elseif ($exception instanceof AccessDeniedException) {
$token = $this->context->getToken();
if (null === $token || $token instanceof AnonymousToken) {
if (!$this->authenticationTrustResolver->isFullFledged($token)) {
if (null !== $this->logger) {
$this->logger->info('Access denied (user is anonymous); redirecting to authentication entry point');
$this->logger->info('Access denied (user is not fully authenticated); redirecting to authentication entry point');
}

try {
Expand All @@ -101,7 +104,7 @@ public function handleException(Event $event)
}
} else {
if (null !== $this->logger) {
$this->logger->info('Access is denied (and user is not anonymous)');
$this->logger->info('Access is denied (and user is neither anonymous, nor remember-me)');
}

if (null === $this->errorPage) {
Expand Down
@@ -0,0 +1,66 @@
<?php

namespace Symfony\Component\Security\Authentication;

use Symfony\Component\Security\Authentication\Token\TokenInterface;

/**
* The default implementation of the authentication trust resolver.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class AuthenticationTrustResolver implements AuthenticationTrustResolverInterface
{
protected $anonymousClass;
protected $rememberMeClass;

/**
* Constructor
*
* @param string $anonymousClass
* @param string $rememberMeClass
*
* @return void
*/
public function __construct($anonymousClass, $rememberMeClass)
{
$this->anonymousClass = $anonymousClass;
$this->rememberMeClass = $rememberMeClass;
}

/**
* {@inheritDoc}
*/
public function isAnonymous(TokenInterface $token = null)
{
if (null === $token) {
return false;
}

return $token instanceof $this->anonymousClass;
}

/**
* {@inheritDoc}
*/
public function isRememberMe(TokenInterface $token = null)
{
if (null === $token) {
return false;
}

return $token instanceof $this->rememberMeClass;
}

/**
* {@inheritDoc}
*/
public function isFullFledged(TokenInterface $token = null)
{
if (null === $token) {
return false;
}

return !$this->isAnonymous($token) && !$this->isRememberMe($token);
}
}
@@ -0,0 +1,53 @@
<?php

namespace Symfony\Component\Security\Authentication;

use Symfony\Component\Security\Authentication\Token\TokenInterface;

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

/**
* Interface for resolving the authentication status of a given token.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface AuthenticationTrustResolverInterface
{
/**
* Resolves whether the passed token implementation is authenticated
* anonymously.
*
* If null is passed, the method must return false.
*
* @param TokenInterface $token
*
* @return Boolean
*/
function isAnonymous(TokenInterface $token = null);

/**
* Resolves whether the passed token implementation is authenticated
* using remember-me capabilities.
*
* @param TokenInterface $token
*
* @return Boolean
*/
function isRememberMe(TokenInterface $token = null);

/**
* Resolves whether the passed token implementation is fully authenticated.
*
* @param TokenInterface $token
*
* @return Boolean
*/
function isFullFledged(TokenInterface $token = null);
}
@@ -0,0 +1,56 @@
<?php

namespace Symfony\Component\Security\Authentication\Token;

use Symfony\Component\Security\Authentication\RememberMe\PersistentTokenInterface;
use Symfony\Component\Security\User\AccountInterface;

/**
* Base class for "Remember Me" tokens
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class RememberMeToken extends Token
{
protected $key;

/**
* The persistent token which resulted in this authentication token.
*
* @var PersistentTokenInterface
*/
protected $persistentToken;

/**
* Constructor.
*
* @param string $username
* @param string $key
*/
public function __construct(AccountInterface $user, $key) {
parent::__construct($user->getRoles());

if (0 === strlen($key)) {
throw new \InvalidArgumentException('$key cannot be empty.');
}

$this->user = $user;
$this->key = $key;
$this->setAuthenticated(true);
}

public function getKey()
{
return $this->key;
}

public function setPersistentToken(PersistentTokenInterface $persistentToken)
{
$this->persistentToken = $persistentToken;
}

public function getPersistentToken()
{
return $this->persistentToken;
}
}
Expand Up @@ -2,8 +2,8 @@

namespace Symfony\Component\Security\Authorization\Voter;

use Symfony\Component\Security\Authentication\AuthenticationTrustResolverInterface;
use Symfony\Component\Security\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Authentication\Token\AnonymousToken;

/*
* This file is part of the Symfony package.
Expand All @@ -15,22 +15,40 @@
*/

/**
* AuthenticatedVoter votes if an attribute like IS_AUTHENTICATED_FULLY or
* IS_AUTHENTICATED_ANONYMOUSLY is present.
* AuthenticatedVoter votes if an attribute like IS_AUTHENTICATED_FULLY,
* IS_AUTHENTICATED_REMEMBERED, or IS_AUTHENTICATED_ANONYMOUSLY is present.
*
* This list is most restrictive to least restrictive checking.
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class AuthenticatedVoter implements VoterInterface
{
const IS_AUTHENTICATED_FULLY = 'IS_AUTHENTICATED_FULLY';
const IS_AUTHENTICATED_REMEMBERED = 'IS_AUTHENTICATED_REMEMBERED';
const IS_AUTHENTICATED_ANONYMOUSLY = 'IS_AUTHENTICATED_ANONYMOUSLY';

protected $authenticationTrustResolver;

/**
* Constructor.
*
* @param AuthenticationTrustResolverInterface $authenticationTrustResolver
*
* @return void
*/
public function __construct(AuthenticationTrustResolverInterface $authenticationTrustResolver)
{
$this->authenticationTrustResolver = $authenticationTrustResolver;
}

/**
* {@inheritdoc}
*/
public function supportsAttribute($attribute)
{
return null !== $attribute && (self::IS_AUTHENTICATED_FULLY === $attribute || self::IS_AUTHENTICATED_ANONYMOUSLY === $attribute);
return null !== $attribute && (self::IS_AUTHENTICATED_FULLY === $attribute || self::IS_AUTHENTICATED_REMEMBERED === $attribute || self::IS_AUTHENTICATED_ANONYMOUSLY === $attribute);
}

/**
Expand All @@ -54,11 +72,21 @@ public function vote(TokenInterface $token, $object, array $attributes)

$result = VoterInterface::ACCESS_DENIED;

if (self::IS_AUTHENTICATED_FULLY === $attribute && !$token instanceof AnonymousToken) {
if (self::IS_AUTHENTICATED_FULLY === $attribute
&& $this->authenticationTrustResolver->isFullFledged($token)) {
return VoterInterface::ACCESS_GRANTED;
}

if (self::IS_AUTHENTICATED_REMEMBERED === $attribute
&& ($this->authenticationTrustResolver->isRememberMe($token)
|| $this->authenticationTrustResolver->isFullFledged($token))) {
return VoterInterface::ACCESS_GRANTED;
}

if (self::IS_AUTHENTICATED_ANONYMOUSLY === $attribute) {
if (self::IS_AUTHENTICATED_ANONYMOUSLY === $attribute
&& ($this->authenticationTrustResolver->isAnonymous($token)
|| $this->authenticationTrustResolver->isRememberMe($token)
|| $this->authenticationTrustResolver->isFullFledged($token))) {
return VoterInterface::ACCESS_GRANTED;
}
}
Expand Down

0 comments on commit abe8047

Please sign in to comment.