Symfony4 Sessions问题

时间:2018-05-22 06:27:59

标签: session symfony4 php-7.2

我目前在Symfony 4中遇到会话管理问题而我无法找到问题所在。 首先是框架配置:

framework:
    secret: '%env(APP_SECRET)%'
    default_locale: '%env(DEFAULT_LOCATE)%'
    #csrf_protection: true
    #http_method_override: true

    # Enables session support. Note that the session will ONLY be started if you read or write from it.
    # Remove or comment this section to explicitly disable session support.
    session:
        handler_id: session.handler.native_file
        save_path: /tmp/registration
        #save_path: '%kernel.project_dir%/var/sessions/%kernel.environment%'

    #esi: true
    #fragments: true
    php_errors:
        log: true

    cache:
        # Put the unique name of your app here: the prefix seed
        # is used to compute stable namespaces for cache keys.
        #prefix_seed: your_vendor_name/app_name

        # The app cache caches to the filesystem by default.
        # Other options include:

        # Redis
        #app: cache.adapter.redis
        #default_redis_provider: redis://localhost

        # APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
        #app: cache.adapter.apcu

安全配置

parameters:
    remember_me_field: '_remember_me'
security:
    access_control:
        -
            path: ^/backend
            roles: ROLE_USER
            #requires_channel: https
        -
            path: ^/admin
            roles: ROLE_USER
            #requires_channel: https
        -
            path: ^/security/login/form
            roles: IS_AUTHENTICATED_ANONYMOUSLY
            #requires_channel: https
        -
            path: ^/security/login/authenticate
            roles: IS_AUTHENTICATED_ANONYMOUSLY
            #requires_channel: https
        -
            path: ^/security/logout
            roles: ROLE_USER
            #requires_channel: https
    # https://symfony.com/doc/current/book/security.html#where-do-users-come-from-user-providers
    encoders:
        Symfony\Component\Security\Core\User\UserInterface:
            algorithm: bcrypt
            cost: 12
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            anonymous: ~
            logout:
                path: /security/login/logout
                target: /security/login/form
            guard:
                authenticators:
                    - App\Security\LoginAuthenticator

            remember_me:
                secret:   '%kernel.secret%'
                lifetime: 31557600 # 1 year in seconds
                path:     /
                remember_me_parameter: '%remember_me_field%'
        default:
            switch_user:
                provider:   ~
                parameter:  _switch_user
                role:       PERMISSION_ALLOWED_TO_SWITCH
            pattern: ^/
            anonymous: ~
            provider: mjr_one

    providers:
        provider:
            entity:
                class: App\Entity\User\User
                property: email

    role_hierarchy:
        #User Type Roles
        ROLE_GUEST:
        ROLE_USER:

和守卫登录

    <?php
    declare(strict_types=1);

    namespace App\Security;

    use App\Entity\User\User;
    use Symfony\Bridge\Doctrine\Security\User\EntityUserProvider;
    use Symfony\Component\DependencyInjection\ContainerInterface;
    use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
    use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
    use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
    use Symfony\Component\HttpFoundation\RedirectResponse;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\Routing\Exception\InvalidParameterException;
    use Symfony\Component\Routing\Exception\MissingMandatoryParametersException;
    use Symfony\Component\Routing\Exception\RouteNotFoundException;
    use Symfony\Component\Routing\Router;
    use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
    use Symfony\Component\Security\Core\Encoder\UserPasswordEncoder;
    use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
    use Symfony\Component\Security\Core\Exception\AuthenticationException;
    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\Core\User\UserProviderInterface;
    use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;


    /**
     * Class LoginAuthenticator
     *
     * @package   app\Security
     * @author    Chris Westerfield <chris@app.one>
     * @link      http://www.app.one
     * @license   properitary
     * @copyright Chris 
     */
    class LoginAuthenticator extends AbstractGuardAuthenticator
    {
        //Routing
        protected const LOGIN_FORM                   = '/security/login/login';
        protected const ROUTER_LOGIN                 = 'security_login_login';
        protected const ROUTER_FORM                  = 'security_login_form';
        //Form
        protected const LOGIN_FORM_USERNAME_FIELD    = '_username';
        protected const LOGIN_FORM_USERNAME_PASSWORD = '_password';
        //Backend
        protected const BACKEND_INDEX                = 'backend_index_index';
        protected const ROLE_BACKEND                 = 'ROLE_TENANT';
        //Admin
        protected const ROLE_ADMIN                   = 'ROLE_ADMIN';
        protected const ADMIN_INDEX                  = 'admin_index_index';
        //User
        protected const USER_INDEX                   = 'index_index';


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

        /**
         * @var UserPasswordEncoder
         */
        protected $encoder;

        /**
         * @var Router
         */
        protected $router;

        /**
         * @var ContainerInterface
         */
        protected $container;

        /**
         * Authenticator constructor.
         *
         * @param Router              $router
         * @param UserPasswordEncoder $encoder
         * @param ContainerInterface  $container
         */
        public function __construct(Router $router, UserPasswordEncoder $encoder, ContainerInterface $container)
        {
            $this->router = $router;
            $this->encoder = $encoder;
            $this->container = $container;
        }

        /**
         * @param Request $request
         *
         * @return array|mixed|null
         */
        public function getCredentials(Request $request)
        : array {
            if ($request->getPathInfo() !== self::LOGIN_FORM || !$request->isMethod('POST')) {
                return [
                    self::LOGIN_FORM_USERNAME_FIELD => null,
                ];
            }

            $user = [
                self::LOGIN_FORM_USERNAME_FIELD    => $request->request->get(self::LOGIN_FORM_USERNAME_FIELD),
                self::LOGIN_FORM_USERNAME_PASSWORD => $request->request->get(self::LOGIN_FORM_USERNAME_PASSWORD),
            ];

            return $user;
        }

        /**
         * @param mixed                 $credentials
         * @param UserProviderInterface $userProvider
         *
         * @return null|UserInterface
         * @throws CustomUserMessageAuthenticationException
         */
        public function getUser($credentials, UserProviderInterface $userProvider)
        : ?UserInterface {
            if (!$userProvider instanceof EntityUserProvider && !$userProvider instanceof UserProviderInterface) {
                return null;
            }

            try {
                return $userProvider->loadUserByUsername($credentials[self::LOGIN_FORM_USERNAME_FIELD]);
            } catch (UsernameNotFoundException $e) {
                throw new CustomUserMessageAuthenticationException($this->failMessage);
            }
        }

        /**
         * @param mixed              $credentials
         * @param UserInterface|User $user
         *
         * @return bool
         * @throws CustomUserMessageAuthenticationException
         */
        public function checkCredentials($credentials, UserInterface $user)
        : bool {
            /** @var User $encoded */
            $plainPassword = $credentials[self::LOGIN_FORM_USERNAME_PASSWORD];

            return $this->encoder->isPasswordValid($user, $plainPassword);
        }

        /**
         * @param Request        $request
         * @param TokenInterface $token
         * @param string         $providerKey
         *
         * @return null|Response
         * @throws \InvalidArgumentException
         * @throws RouteNotFoundException
         * @throws MissingMandatoryParametersException
         * @throws InvalidParameterException
         * @throws AuthenticationCredentialsNotFoundException
         * @throws InvalidArgumentException
         * @throws ServiceNotFoundException
         * @throws ServiceCircularReferenceException
         */
        public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
        : ?Response {
            /** @var User $user */
            $user = $token->getUser();
            $roles = $user->getRoles();
            $validation = $this->container->get('security.authorization_checker');
            if ($validation->isGranted(self::ROLE_BACKEND)) {
                $url = $this->router->generate(self::BACKEND_INDEX);
            } else {
                if ($validation->isGranted(self::ROLE_ADMIN)) {
                    $url = $this->router->generate(self::ADMIN_INDEX);
                } else {
                    $url = $this->router->generate(self::USER_INDEX);
                }
            }
            return new RedirectResponse($url);
        }

        /**
         * @param Request                 $request
         * @param AuthenticationException $exception
         *
         * @return null|Response
         * @throws \InvalidArgumentException
         */
        public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
        : ?Response {
            $request->getSession()->set(Security::AUTHENTICATION_ERROR, $exception);
            $url = $this->router->generate(self::ROUTER_FORM);

            return new RedirectResponse($url);
        }

        /**
         * @param Request                      $request
         * @param AuthenticationException|null $authException
         *
         * @return Response
         * @throws RouteNotFoundException
         * @throws MissingMandatoryParametersException
         * @throws \InvalidArgumentException
         * @throws InvalidParameterException
         */
        public function start(Request $request, AuthenticationException $authException = null)
        : Response {
            $url = $this->router->generate(self::ROUTER_LOGIN);

            return new RedirectResponse($url);
        }

        /**
         * @return bool
         */
        public function supportsRememberMe()
        : bool
        {
            $request = $this->container->get('request_stack')->getCurrentRequest();;
            $field = $this->container->getParameter('remember_me_field');
            return $request->request->has($field);
        }

        /**
         * @param Request $request
         *
         * @return bool
         */
        public function supports(Request $request)
        : bool {
            if ($request->getMethod() === 'POST' && $request->request->has(self::LOGIN_FORM_USERNAME_FIELD) && $request->request->has(self::LOGIN_FORM_USERNAME_PASSWORD)) {
                return true;
            }
            return false;
        }
    }

我的问题是我总是得到一个新的会话ID。 但我不知道我在哪里错误配置了Symfony。 即使是记忆选项也没有帮助 我还认识到,security.token不包含任何令牌。 我对系统进行了调试,并认识到每次请求都会触发destroy方法。 但我不知道我发生了什么事情。 任何帮助都是有效的

: - )

克里斯

到目前为止我发现的是:

如果我查看&#39; @ security.token_storage&#39;的内容。我得到了什么服务

TokenStorage {#1180 ▼
  -token: null
}

但如果我在控制器中检查它:

我明白了:

TokenStorage {#1180 ▼
  -token: RememberMeToken {#2357 ▶}
}

在日志中我没有看到任何错误。对我来说似乎很奇怪的唯一部分是:

  • 尝试刷新后,Token被取消了身份验证。
  • 检查防护身份验证凭据。
  • 在警卫配置器上调用getCredentials()。
  • 记住我检测到Cookie。

这对我来说很奇怪。

在我忘记之前,我使用Symfony 4.0.10和php 7.2.5

1 个答案:

答案 0 :(得分:0)

查看了所有服务后,我发现了它。 我计划在过滤器中使用需要令牌存储的服务。 目前在我看来,这个服务获得一个空的空token_storage,它会覆盖所有未来的实例。 我删除了监听器,系统按预期再次工作。