记住我在symfony 3.3中没有使用防护认证

时间:2017-11-10 09:29:58

标签: php symfony

我正在使用symfony 3.3微框架。我没有使用FOSUserbundle,因为我没有用户名和电子邮件(由于社交登录不是必需的)。我使用symfonys保护认证系统使用自定义身份验证。一切正常,但是当我要实现REMEMBER me功能时。它不起作用。以下是我用过的各种文件。

security.yml

# To get started with security, check out the documentation:
# http://symfony.com/doc/current/security.html
security:

    encoders:
        AdminBundle\Entity\User:
            algorithm: bcrypt

    role_hierarchy:
        ROLE_ADMIN:       ROLE_ADMIN
        ROLE_USER:        ROLE_USER

    providers:
        in_memory:
           memory: ~
        token_user_provider:
            entity:
                class: AdminBundle:User
                property: authToken

        login_form_provider:
            entity:
                class: AdminBundle:User
                property: email

    firewalls:
        main:
            pattern: ^/api/
            provider: token_user_provider
            logout:       true
            anonymous:    true
            guard:
                authenticators:
                    - api_key_authenticator
        admin:
            anonymous: ~
            provider: login_form_provider
            logout:
                path:   admin_logout
                target: admin_login
            guard:
                authenticators:
                    - form_authenticator
            remember_me:
                secret:   '%secret%'
                lifetime: 604800     # 1 week
                path:     ^/admin/

    access_control:
        - { path: ^/admin/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/admin/forgot-password, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/admin/reset-password, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/admin/, roles: [IS_AUTHENTICATED_FULLY,IS_AUTHENTICATED_REMEMBERED] }
        - { path: ^/api/user/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/api/user/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/api/user/forgot-password, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/api/page/about-us, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/api/page/terms-and-condition, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/api/page/faq, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/api/page/privacy-policy, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/api/consent/submit, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/api/, roles: ROLE_USER }

LoginFormAuthenticator.php

<?php

namespace AdminBundle\Security;

use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;

class LoginFormAuthenticator extends AbstractGuardAuthenticator {

    /**
     * @var \Symfony\Component\Routing\RouterInterface
     */
    private $router;

    /**
     * @var \Symfony\Component\DependencyInjection\ContainerInterface
     */
    private $container;

    /**
     * Default message for authentication failure.
     *
     * @var string
     */
    private $failMessage = 'Invalid credentials';

    /**
     * Creates a new instance of FormAuthenticator
     */
    public function __construct(RouterInterface $router, ContainerInterface $container) {
        $this->router = $router;
        $this->container = $container;
    }

    /**
     * {@inheritdoc}
     */
    public function getCredentials(Request $request) {

        if ($request->get('_route') != 'admin_login' || !$request->isMethod('POST')) {
            return null;
        }

        // Check invalid CSRF token
        $csrfToken = $request->request->get('_csrf_token');
        $csrftokenManager = $this->container->get('security.csrf.token_manager');
        if (false === $csrftokenManager->isTokenValid(new CsrfToken('authenticate', $csrfToken))) {
            throw new InvalidCsrfTokenException('Invalid CSRF token.');
        }

        return array(
            'email' => $request->request->get('email'),
            'password' => $request->request->get('password'),
        );
    }

    /**
     * {@inheritdoc}
     */
    public function getUser($credentials, UserProviderInterface $userProvider) {
        try {
            return $userProvider->loadUserByUsername($credentials['email']);
        } catch (UsernameNotFoundException $e) {
            throw new CustomUserMessageAuthenticationException($this->failMessage);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function checkCredentials($credentials, UserInterface $user) {

        if(!in_array('ROLE_ADMIN', $user->getRoles()))
        {
            throw new CustomUserMessageAuthenticationException("You don't have right to access this page.");
        }

        $factory = $this->container->get('security.encoder_factory');
        $encoder = $factory->getEncoder($user);
        $salt = $user->getSalt();
        if($encoder->isPasswordValid($user->getPassword(), $credentials['password'], $salt)) {
            return true;
        }

        throw new CustomUserMessageAuthenticationException($this->failMessage);
    }

    /**
     * {@inheritdoc}
     */
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey) {
        $url = $this->router->generate('admin_dashboard');
        return new RedirectResponse($url);
    }

    /**
     * {@inheritdoc}
     */
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception) {
        $request->getSession()->set(Security::AUTHENTICATION_ERROR, $exception);
        $url = $this->router->generate('admin_login');
        return new RedirectResponse($url);
    }

    /**
     * {@inheritdoc}
     */
    public function start(Request $request, AuthenticationException $authException = null) {
        $url = $this->router->generate('admin_login');
        return new RedirectResponse($url);
    }

    /**
     * {@inheritdoc}
     */
    public function supportsRememberMe() {
        return true;
    }

}

dev.log

[2017-11-10 14:44:24] request.INFO: Matched route "admin_dashboard". {"route":"admin_dashboard","route_parameters":{"_controller":"AdminBundle\\Controller\\DashboardController::indexAction","_route":"admin_dashboard"},"request_uri":"http://localhost/bitcoin-consentsy/public/index.php/admin/dashboard","method":"GET"} []
[2017-11-10 14:44:24] security.DEBUG: Checking for guard authentication credentials. {"firewall_key":"admin","authenticators":1} []
[2017-11-10 14:44:24] security.DEBUG: Calling getCredentials() on guard configurator. {"firewall_key":"admin","authenticator":"AdminBundle\\Security\\LoginFormAuthenticator"} []
[2017-11-10 14:44:24] security.DEBUG: Remember-me cookie detected. [] []
[2017-11-10 14:44:25] doctrine.DEBUG: SELECT t0.id AS id_1, t0.email AS email_2, t0.password AS password_3, t0.is_active AS is_active_4, t0.device_id AS device_id_5, t0.device_type AS device_type_6, t0.provide AS provide_7, t0.identifier AS identifier_8, t0.roles AS roles_9, t0.auth_token AS auth_token_10, t0.reset_token AS reset_token_11, t0.is_registration_mail_sent AS is_registration_mail_sent_12, t0.firstname AS firstname_13, t0.lastname AS lastname_14, t0.created_at AS created_at_15, t0.updated_at AS updated_at_16 FROM users t0 WHERE t0.email = ? LIMIT 1 [""] []
[2017-11-10 14:44:25] security.INFO: User for remember-me cookie not found. [] []
[2017-11-10 14:44:25] security.DEBUG: Clearing remember-me cookie. {"name":"REMEMBERME"} []
[2017-11-10 14:44:25] security.INFO: Populated the TokenStorage with an anonymous Token. [] []
[2017-11-10 14:44:25] security.DEBUG: Access denied, the user is not fully authenticated; redirecting to authentication entry point. {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException(code: 403): Access Denied. at E:\\xampp\\htdocs\\bitcoin-consentsy\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\Security\\Http\\Firewall\\AccessListener.php:70)"} []

请帮我解决这个问题。感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

好的,我找到了。

“警告:如果用户使用”记住我“功能登录,则单独检查'IS_AUTHENTICATED_FULLY'将返回false。”

所以,只需用 IS_AUTHENTICATED_REMEMBERED

替换 IS_AUTHENTICATED_FULLY

How to check if an user is logged in Symfony2 inside a controller?

享受