如何在Symfony 3上的控制器(带有或不带有FOSUserBundle)中手动验证(登录)用户

本文概述

  • 怎么做
  • 定制登录控制器示例
当我们谈论用户的操纵, 登录和注册表格等时, 诸如FOSUserBundle之类的工具使事情变得非常简单, 谁能拒绝呢?可能是那些需要控制一切并了解其工作原理的人。这就是为什么某些开发人员即使不使用FOSUserBundle而是希望手动处理这些事件的原因。
寻找使用你自己的代码从控制器登录用户?你找到了学习它的正确地方。在本文中, 你将学习如何在Symfony应用程序上自动登录用户(带有或不带有凭据)。
怎么做你首先需要在控制器中导入一些类, 即InteractiveLoginEvent和UsernamePasswordToken。然后, 使用Doctrine的实体管理器或FOSUserBundle的用户管理器自行查找用户。如果你使用的是FOSUser, 则用户应存储在变量中, 并且代表FOS \ UserBundle \ Model \ User的实例;如果不使用, 则仅表示User。接下来, 继续创建令牌并在令牌存储服务中进行设置。创建令牌的类期望将用户对象作为第一个参数, 因为第二个参数通常是用户的密码, 但是可以为null。作为第三个参数, 你需要提供要使用的防火墙的名称, 它通常是主要的, 但是如果有其他名称, 则值得检查你的security.yml文件。作为第四个参数, 你需要提供用户的角色。
你还需要将类生成的令牌存储在会话中, 最后手动调度交互式登录事件:
< ?phpnamespace AppBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; class SomeController extends Controller{public function loginAction(Request $request){$user = /*The user needs to be registered */; #// Example of how to obtain an user://$user = $this-> getDoctrine()-> getManager()-> getRepository("AppBundle/Entity/User")-> findOneBy(array('username' => "some user name example")); //Handle getting or creating the user entity likely with a posted form// The third parameter "main" can change according to the name of your firewall in security.yml$token = new UsernamePasswordToken($user, null, 'main', $user-> getRoles()); $this-> get('security.token_storage')-> setToken($token); // If the firewall name is not main, then the set value would be instead:// $this-> get('session')-> set('_security_XXXFIREWALLNAMEXXX', serialize($token)); $this-> get('session')-> set('_security_main', serialize($token)); // Fire the login event manually$event = new InteractiveLoginEvent($request, $token); $this-> get("event_dispatcher")-> dispatch("security.interactive_login", $event); /** Now the user is authenticated !!!! * Do what you need to do now, like render a view, redirect to route etc.*/}}

完成此操作后, 你已自动在会话中登录了一个用户, 但是未检查该用户的凭据。
定制登录控制器示例假设你正在创建一些自定义登录表单(或覆盖FOSUserBundle的默认登录表单), 并且需要手动验证用户。为此, 第一个控制器示例仅可用于设置会话中的用户, 但是由于我们既不验证用户名也不验证密码, 因此它实际上并未进行身份验证。
在会话中设置用户之前, 我们需要做的第一步是验证他提供的凭据是否正确。为此, 我们需要控制器中的安全编码服务来检查Providen数据的真实性。在此示例中, 我们将以基本逻辑向你展示身份验证过程的工作方式:
< ?phpnamespace AppBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; class SomeController extends Controller{public function loginAction(Request $request){// This data is most likely to be retrieven from the Request object (from Form)// But to make it easy to understand ...$_username = "batman"; $_password = "batmobil"; // Retrieve the security encoder of symfony$factory = $this-> get('security.encoder_factory'); /// Start retrieve user// Let's retrieve the user by its username:// If you are using FOSUserBundle:$user_manager = $this-> get('fos_user.user_manager'); $user = $user_manager-> findUserByUsername($_username); // Or by yourself$user = $this-> getDoctrine()-> getManager()-> getRepository("userBundle:User")-> findOneBy(array('username' => $_username)); /// End Retrieve user// Check if the user exists !if(!$user){return new Response('Username doesnt exists', Response::HTTP_UNAUTHORIZED, array('Content-type' => 'application/json')); }/// Start verification$encoder = $factory-> getEncoder($user); $salt = $user-> getSalt(); if(!$encoder-> isPasswordValid($user-> getPassword(), $_password, $salt)) {return new Response('Username or Password not valid.', Response::HTTP_UNAUTHORIZED, array('Content-type' => 'application/json')); } /// End Verification// The password matches ! then proceed to set the user in session//Handle getting or creating the user entity likely with a posted form// The third parameter "main" can change according to the name of your firewall in security.yml$token = new UsernamePasswordToken($user, null, 'main', $user-> getRoles()); $this-> get('security.token_storage')-> setToken($token); // If the firewall name is not main, then the set value would be instead:// $this-> get('session')-> set('_security_XXXFIREWALLNAMEXXX', serialize($token)); $this-> get('session')-> set('_security_main', serialize($token)); // Fire the login event manually$event = new InteractiveLoginEvent($request, $token); $this-> get("event_dispatcher")-> dispatch("security.interactive_login", $event); /** Now the user is authenticated !!!! * Do what you need to do now, like render a view, redirect to route etc.*/return new Response('Welcome '. $user-> getUsername(), Response::HTTP_OK, array('Content-type' => 'application/json')); }}

【如何在Symfony 3上的控制器(带有或不带有FOSUserBundle)中手动验证(登录)用户】编码愉快!

    推荐阅读