Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/grails/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带开放ID的蒸汽认证(Symfony 4.x)_Symfony_Steam - Fatal编程技术网

带开放ID的蒸汽认证(Symfony 4.x)

带开放ID的蒸汽认证(Symfony 4.x),symfony,steam,Symfony,Steam,我尝试使用两种方法在我的网站中进行身份验证: 使用电子邮件地址/密码(工作) 使用蒸汽(我有问题的地方) 这是我的服务。yaml: security: encoders: App\Entity\User\User: algorithm: bcrypt providers: user_provider: entity: class: App\Entity\User\User steam_provider: id:

我尝试使用两种方法在我的网站中进行身份验证:

  • 使用电子邮件地址/密码(工作)

  • 使用蒸汽(我有问题的地方)

  • 这是我的
    服务。yaml

    security:
      encoders:
        App\Entity\User\User:
          algorithm: bcrypt
      providers:
        user_provider:
          entity:
            class: App\Entity\User\User
        steam_provider:
          id: App\Security\SteamAuth\User\SteamUserProvider
        chain_provider:
          chain:
            providers: [user_provider, steam_provider]
      firewalls:
        dev:
          pattern: ^/(_(profiler|wdt)|css|images|js)/
          security: false
        steam:
          anonymous: ~
          pattern: /steam/login
          user_checker: App\Security\User\UserChecker
          provider: steam_provider
          steam: true
          logout:
            path:   /logout
            target: /
        classic:
          anonymous: true
          user_checker: App\Security\User\UserChecker
          provider: user_provider
          form_login:
            provider: user_provider
            default_target_path: /servers
            use_referer: true
            login_path: /login
            check_path: /login
            username_parameter: login_form[emailAddress]
            password_parameter: login_form[password]
          remember_me:
            remember_me_parameter: login_form[remember_me]
            secret: '%kernel.secret%'
            lifetime: 1209600 # 2 week in seconds
            path: /
          logout:
            target: /
      access_control:
        # Users
        - { path: '^/steam/login', roles: IS_AUTHENTICATED_ANONYMOUSLY }
    
    与其他服务相比,Steam仅使用OpenID提供身份验证。没问题,我更新了我的代码以使用OpenID

    在我看来,一切都很好,即使token是正确的。主要问题是在重新加载页面之后。身份验证令牌丢失,我已作为匿名用户进行身份验证。如您所见,无论发生什么情况,我都会将用户重定向到
    /login
    (如果用户经过身份验证,我就可以从该页面重定向)

    这是我的密码:

    SteamListener.php

    <?php declare(strict_types = 1);
    
    namespace App\Security\SteamAuth\Firewall;
    
    use App\Security\SteamAuth\Authentication\Token\SteamUserToken;
    use Symfony\Component\HttpFoundation\RedirectResponse;
    use Symfony\Component\HttpKernel\Event\RequestEvent;
    use Symfony\Component\Routing\RouterInterface;
    use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
    use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
    use Symfony\Component\Security\Core\Exception\AuthenticationException;
    
    /**
     * Class SteamListener
     * @package App\Security\SteamAuth\Firewall
     */
    class SteamListener
    {
        /**
         * @var AuthenticationManagerInterface
         */
        private $authenticationManager;
    
        /**
         * @var RouterInterface
         */
        private $router;
    
        /**
         * @var TokenStorageInterface
         */
        private $tokenStorage;
    
        /**
         * SteamListener constructor.
         *
         * @param AuthenticationManagerInterface $authenticationManager
         * @param TokenStorageInterface          $tokenStorage
         * @param RouterInterface                $router
         */
        public function __construct(AuthenticationManagerInterface $authenticationManager, TokenStorageInterface $tokenStorage, RouterInterface $router)
        {
            $this->authenticationManager = $authenticationManager;
            $this->tokenStorage          = $tokenStorage;
            $this->router                = $router;
        }
    
        /**
         * Try to authenticate user based on SteamID.
         *
         * @param RequestEvent $event
         */
        public function __invoke(RequestEvent $event)
        {
            $request   = $event->getRequest();
            $claimedId = str_replace('https://steamcommunity.com/openid/id/', '', $request->query->get('openid_claimed_id'));
    
            try {
                $token = new SteamUserToken($claimedId);
                $token->setAttributes($request->query->all());
    
                $authToken = $this->authenticationManager->authenticate($token);
                $this->tokenStorage->setToken($authToken);
            } catch (AuthenticationException $exception) {
                $token = $this->tokenStorage->getToken();
                if ($token instanceof SteamUserToken) {
                    $this->tokenStorage->setToken(null);
                }
            }
    
            $event->setResponse(new RedirectResponse($this->router->generate('login')));
        }
    }
    
    <?php declare(strict_types = 1);
    
    namespace App\Security\SteamAuth\Authentication\Provider;
    
    use App\Security\SteamAuth\Authentication\Token\SteamUserToken;
    use Symfony\Component\HttpClient\HttpClient;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface;
    use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
    use Symfony\Component\Security\Core\Exception\AuthenticationException;
    use Symfony\Component\Security\Core\User\UserProviderInterface;
    use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
    use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
    use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
    use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
    
    /**
     * Class SteamProvider
     * @package App\Security\SteamAuth\Provider
     */
    class SteamProvider implements AuthenticationProviderInterface
    {
        const ACCEPTED_RESPONSE = "ns:http://specs.openid.net/auth/2.0\nis_valid:true\n";
    
        /**
         * This actually points to UserRepository.
         *
         * @var UserProviderInterface
         */
        private $userProvider;
    
        /**
         * SteamProvider constructor.
         *
         * @param UserProviderInterface $userProvider
         */
        public function __construct(UserProviderInterface $userProvider)
        {
            $this->userProvider = $userProvider;
        }
    
        /**
         * {@inheritDoc}
         *
         * Note: Token is an instance of SteamUserToken.
         */
        public function authenticate(TokenInterface $token)
        {
            if (!$user = $this->userProvider->loadUserByUsername($token->getUsername())) {
                throw new AuthenticationException('Steam auth is invalid!');
            }
    
            if ($token->getAttribute('openid_ns') !== 'http://specs.openid.net/auth/2.0') {
                throw new AuthenticationException('Steam token is invalid!');
            }
    
            // Validate SteamID before authenticating user.
            $checkAuth                = $token->getAttributes();
            $checkAuth['openid_mode'] = 'check_authentication';
    
            try {
                $request  = HttpClient::create();
                $response = $request->request(Request::METHOD_GET, $checkAuth['openid_op_endpoint'], ['query' => $checkAuth]);
                if ($response->getContent() !== self::ACCEPTED_RESPONSE) {
                    throw new AuthenticationException('Steam token is invalid!');
                }
    
                $authToken = new SteamUserToken($token->getUsername(), $user->getRoles());
                $authToken->setUser($user);
    
                return $authToken;
            } catch (ClientExceptionInterface|RedirectionExceptionInterface|ServerExceptionInterface|TransportExceptionInterface $e) {
                throw new AuthenticationException('Steam token is invalid!');
            }
        }
    
        /**
         * {@inheritDoc}
         */
        public function supports(TokenInterface $token)
        {
            return $token instanceof SteamUserToken;
        }
    }
    
    <?php declare(strict_types = 1);
    
    namespace App\Security\SteamAuth\Authentication\Token;
    
    use App\Entity\User\User;
    use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
    use Symfony\Component\Security\Core\User\UserInterface;
    
    /**
     * Class SteamUserToken
     * @package App\Security\SteamAuth\Authentication
     */
    class SteamUserToken implements TokenInterface
    {
        /**
         * @var array
         */
        private $attributes = [];
    
        /**
         * @var bool
         */
        private $authenticated = false;
    
        /**
         * @var User|null
         */
        private $user = null;
    
        /**
         * @var array
         */
        private $roles = [];
    
        /**
         * @var string|null
         */
        private $steamId = null;
    
        /**
         * SteamUserToken constructor.
         *
         * @param string $steamId
         * @param array  $roles
         */
        public function __construct(string $steamId, array $roles = [])
        {
            $this->steamId       = $steamId;
            $this->roles         = $roles;
            $this->authenticated = \count($roles) > 0;
        }
    
        /**
         * {@inheritDoc}
         */
        public function getUser()
        {
            return $this->user;
        }
    
        /**
         * {@inheritDoc}
         * @var $user UserInterface
         */
        public function setUser($user)
        {
            $this->user = $user;
        }
    
    
        /**
         * {@inheritDoc}
         */
        public function getUsername()
        {
            return $this->steamId;
        }
    
        /**
         * {@inheritDoc}
         */
        public function getRoles()
        {
            if (!$this->user) {
                return [];
            }
    
            return $this->roles;
        }
    
        /**
         * @param array $roles
         */
        public function setRoles(array $roles = [])
        {
            $this->roles = $roles;
        }
    
        /**
         * {@inheritDoc}
         */
        public function getRoleNames()
        {
            return array_map(function ($role) {return $role;}, $this->user ? $this->user->getRoles() : []);
        }
    
        /**
         * {@inheritDoc}
         */
        public function getCredentials()
        {
            return '';
        }
    
        /**
         * {@inheritDoc}
         */
        public function isAuthenticated()
        {
            return $this->authenticated;
        }
    
        /**
         * {@inheritDoc}
         */
        public function setAuthenticated($authenticated)
        {
            $this->authenticated = $authenticated;
        }
    
        /**
         * {@inheritDoc}
         */
        public function eraseCredentials()
        {
            if ($this->getUser() instanceof UserInterface) {
                $this->getUser()->eraseCredentials();
            }
        }
    
        /**
         * {@inheritDoc}
         */
        public function serialize()
        {
            return serialize($this->__serialize());
        }
    
        /**
         * {@inheritDoc}
         */
        public function __serialize(): array
        {
            return [$this->attributes, $this->authenticated, $this->steamId, $this->roles, $this->user];
        }
    
        /**
         * {@inheritDoc}
         */
        public function unserialize($serialized)
        {
            $this->__unserialize(unserialize($serialized));
        }
    
        /**
         * {@inheritDoc}
         */
        public function __unserialize(array $data): void
        {
            [$this->attributes, $this->authenticated, $this->steamId, $this->roles, $this->user] = $data;
        }
    
        /**
         * {@inheritDoc}
         */
        public function getAttributes()
        {
            return $this->attributes;
        }
    
        /**
         * {@inheritDoc}
         */
        public function setAttributes(array $attributes)
        {
            $this->attributes = $attributes;
        }
    
        /**
         * {@inheritDoc}
         */
        public function hasAttribute($name)
        {
            return \array_key_exists($name, $this->attributes);
        }
    
        /**
         * {@inheritDoc}
         */
        public function getAttribute($name)
        {
            if (!\array_key_exists($name, $this->attributes)) {
                throw new \InvalidArgumentException(sprintf('This token has no "%s" attribute.', $name));
            }
    
            return $this->attributes[$name];
        }
    
        /**
         * {@inheritDoc}
         */
        public function setAttribute($name, $value)
        {
            $this->attributes[$name] = $value;
        }
    
        /**
         * {@inheritDoc}
         */
        public function __toString()
        {
            if (!$this->user) {
                return '-';
            }
    
            return $this->user->getUsername();
        }
    }
    
    streamusertoken.php

    <?php declare(strict_types = 1);
    
    namespace App\Security\SteamAuth\Firewall;
    
    use App\Security\SteamAuth\Authentication\Token\SteamUserToken;
    use Symfony\Component\HttpFoundation\RedirectResponse;
    use Symfony\Component\HttpKernel\Event\RequestEvent;
    use Symfony\Component\Routing\RouterInterface;
    use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
    use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
    use Symfony\Component\Security\Core\Exception\AuthenticationException;
    
    /**
     * Class SteamListener
     * @package App\Security\SteamAuth\Firewall
     */
    class SteamListener
    {
        /**
         * @var AuthenticationManagerInterface
         */
        private $authenticationManager;
    
        /**
         * @var RouterInterface
         */
        private $router;
    
        /**
         * @var TokenStorageInterface
         */
        private $tokenStorage;
    
        /**
         * SteamListener constructor.
         *
         * @param AuthenticationManagerInterface $authenticationManager
         * @param TokenStorageInterface          $tokenStorage
         * @param RouterInterface                $router
         */
        public function __construct(AuthenticationManagerInterface $authenticationManager, TokenStorageInterface $tokenStorage, RouterInterface $router)
        {
            $this->authenticationManager = $authenticationManager;
            $this->tokenStorage          = $tokenStorage;
            $this->router                = $router;
        }
    
        /**
         * Try to authenticate user based on SteamID.
         *
         * @param RequestEvent $event
         */
        public function __invoke(RequestEvent $event)
        {
            $request   = $event->getRequest();
            $claimedId = str_replace('https://steamcommunity.com/openid/id/', '', $request->query->get('openid_claimed_id'));
    
            try {
                $token = new SteamUserToken($claimedId);
                $token->setAttributes($request->query->all());
    
                $authToken = $this->authenticationManager->authenticate($token);
                $this->tokenStorage->setToken($authToken);
            } catch (AuthenticationException $exception) {
                $token = $this->tokenStorage->getToken();
                if ($token instanceof SteamUserToken) {
                    $this->tokenStorage->setToken(null);
                }
            }
    
            $event->setResponse(new RedirectResponse($this->router->generate('login')));
        }
    }
    
    <?php declare(strict_types = 1);
    
    namespace App\Security\SteamAuth\Authentication\Provider;
    
    use App\Security\SteamAuth\Authentication\Token\SteamUserToken;
    use Symfony\Component\HttpClient\HttpClient;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface;
    use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
    use Symfony\Component\Security\Core\Exception\AuthenticationException;
    use Symfony\Component\Security\Core\User\UserProviderInterface;
    use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
    use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
    use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
    use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
    
    /**
     * Class SteamProvider
     * @package App\Security\SteamAuth\Provider
     */
    class SteamProvider implements AuthenticationProviderInterface
    {
        const ACCEPTED_RESPONSE = "ns:http://specs.openid.net/auth/2.0\nis_valid:true\n";
    
        /**
         * This actually points to UserRepository.
         *
         * @var UserProviderInterface
         */
        private $userProvider;
    
        /**
         * SteamProvider constructor.
         *
         * @param UserProviderInterface $userProvider
         */
        public function __construct(UserProviderInterface $userProvider)
        {
            $this->userProvider = $userProvider;
        }
    
        /**
         * {@inheritDoc}
         *
         * Note: Token is an instance of SteamUserToken.
         */
        public function authenticate(TokenInterface $token)
        {
            if (!$user = $this->userProvider->loadUserByUsername($token->getUsername())) {
                throw new AuthenticationException('Steam auth is invalid!');
            }
    
            if ($token->getAttribute('openid_ns') !== 'http://specs.openid.net/auth/2.0') {
                throw new AuthenticationException('Steam token is invalid!');
            }
    
            // Validate SteamID before authenticating user.
            $checkAuth                = $token->getAttributes();
            $checkAuth['openid_mode'] = 'check_authentication';
    
            try {
                $request  = HttpClient::create();
                $response = $request->request(Request::METHOD_GET, $checkAuth['openid_op_endpoint'], ['query' => $checkAuth]);
                if ($response->getContent() !== self::ACCEPTED_RESPONSE) {
                    throw new AuthenticationException('Steam token is invalid!');
                }
    
                $authToken = new SteamUserToken($token->getUsername(), $user->getRoles());
                $authToken->setUser($user);
    
                return $authToken;
            } catch (ClientExceptionInterface|RedirectionExceptionInterface|ServerExceptionInterface|TransportExceptionInterface $e) {
                throw new AuthenticationException('Steam token is invalid!');
            }
        }
    
        /**
         * {@inheritDoc}
         */
        public function supports(TokenInterface $token)
        {
            return $token instanceof SteamUserToken;
        }
    }
    
    <?php declare(strict_types = 1);
    
    namespace App\Security\SteamAuth\Authentication\Token;
    
    use App\Entity\User\User;
    use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
    use Symfony\Component\Security\Core\User\UserInterface;
    
    /**
     * Class SteamUserToken
     * @package App\Security\SteamAuth\Authentication
     */
    class SteamUserToken implements TokenInterface
    {
        /**
         * @var array
         */
        private $attributes = [];
    
        /**
         * @var bool
         */
        private $authenticated = false;
    
        /**
         * @var User|null
         */
        private $user = null;
    
        /**
         * @var array
         */
        private $roles = [];
    
        /**
         * @var string|null
         */
        private $steamId = null;
    
        /**
         * SteamUserToken constructor.
         *
         * @param string $steamId
         * @param array  $roles
         */
        public function __construct(string $steamId, array $roles = [])
        {
            $this->steamId       = $steamId;
            $this->roles         = $roles;
            $this->authenticated = \count($roles) > 0;
        }
    
        /**
         * {@inheritDoc}
         */
        public function getUser()
        {
            return $this->user;
        }
    
        /**
         * {@inheritDoc}
         * @var $user UserInterface
         */
        public function setUser($user)
        {
            $this->user = $user;
        }
    
    
        /**
         * {@inheritDoc}
         */
        public function getUsername()
        {
            return $this->steamId;
        }
    
        /**
         * {@inheritDoc}
         */
        public function getRoles()
        {
            if (!$this->user) {
                return [];
            }
    
            return $this->roles;
        }
    
        /**
         * @param array $roles
         */
        public function setRoles(array $roles = [])
        {
            $this->roles = $roles;
        }
    
        /**
         * {@inheritDoc}
         */
        public function getRoleNames()
        {
            return array_map(function ($role) {return $role;}, $this->user ? $this->user->getRoles() : []);
        }
    
        /**
         * {@inheritDoc}
         */
        public function getCredentials()
        {
            return '';
        }
    
        /**
         * {@inheritDoc}
         */
        public function isAuthenticated()
        {
            return $this->authenticated;
        }
    
        /**
         * {@inheritDoc}
         */
        public function setAuthenticated($authenticated)
        {
            $this->authenticated = $authenticated;
        }
    
        /**
         * {@inheritDoc}
         */
        public function eraseCredentials()
        {
            if ($this->getUser() instanceof UserInterface) {
                $this->getUser()->eraseCredentials();
            }
        }
    
        /**
         * {@inheritDoc}
         */
        public function serialize()
        {
            return serialize($this->__serialize());
        }
    
        /**
         * {@inheritDoc}
         */
        public function __serialize(): array
        {
            return [$this->attributes, $this->authenticated, $this->steamId, $this->roles, $this->user];
        }
    
        /**
         * {@inheritDoc}
         */
        public function unserialize($serialized)
        {
            $this->__unserialize(unserialize($serialized));
        }
    
        /**
         * {@inheritDoc}
         */
        public function __unserialize(array $data): void
        {
            [$this->attributes, $this->authenticated, $this->steamId, $this->roles, $this->user] = $data;
        }
    
        /**
         * {@inheritDoc}
         */
        public function getAttributes()
        {
            return $this->attributes;
        }
    
        /**
         * {@inheritDoc}
         */
        public function setAttributes(array $attributes)
        {
            $this->attributes = $attributes;
        }
    
        /**
         * {@inheritDoc}
         */
        public function hasAttribute($name)
        {
            return \array_key_exists($name, $this->attributes);
        }
    
        /**
         * {@inheritDoc}
         */
        public function getAttribute($name)
        {
            if (!\array_key_exists($name, $this->attributes)) {
                throw new \InvalidArgumentException(sprintf('This token has no "%s" attribute.', $name));
            }
    
            return $this->attributes[$name];
        }
    
        /**
         * {@inheritDoc}
         */
        public function setAttribute($name, $value)
        {
            $this->attributes[$name] = $value;
        }
    
        /**
         * {@inheritDoc}
         */
        public function __toString()
        {
            if (!$this->user) {
                return '-';
            }
    
            return $this->user->getUsername();
        }
    }
    

    我刚刚浏览了一下,您已经提到了我觉得有点可疑的领域--
    SteamListener::\u invoke
    方法。对我来说,您总是在该方法的底部设置登录页面的重定向响应,这似乎很奇怪,但基于此,我希望在设置令牌后返回
    。但是你已经说过它不是。如果在该方法中的
    $event->setResponse()
    调用周围放置一个条件,会有任何影响吗?例如
    if(!$token){//set redirect response
    谢谢您的回复!让我解释一下为什么我使用
    \u invoke
    而不是
    handle
    。从Symfony 4.3开始,该接口被声明为已弃用。现在,让我看看我是否理解正确。您想让我这样做:@mickadoo再添加一件事。如果我添加
    return;
    设置令牌后,我将重定向我的自定义控制器::方法。只有一行:
    抛出新异常(“如果您到达此页面,请与管理员联系!”)
    。我评论了那一行,我正在转储当前用户,猜猜怎么着?它显示了我的帐户!在我更改页面后,所有内容都丢失了。知道吗?可能我的序列化不好?或者防火墙?抱歉,我没有看到你回复我。我对steam身份验证不是100%熟悉,但当我使用OAuth服务时,它将令牌存储在本地客户端上的存储,然后将其包含在每个后续请求中。令牌存储在数据库中,并具有过期日期。您是否正在执行类似操作?@mickadoo我没有使用数据库存储会话令牌。我使用的是Symfony默认使用的系统本地文件。