Symfony 2.3 自定义表单 login_check

Symfony 2.3 custom form login_check

我已经成功创建了一个登录系统,该系统检查了一个原则用户实体 class 并成功进行了身份验证。这使用 http_basic 设置在防火墙块中:

app/config/security.yml

但是我希望使用 form_login 选项并呈现我自己的自定义登录模板。下面是 app/config/security.yml 在我进行更改以使用呈现我的自定义表单的表单登录后:

security:
encoders:
    Brs\UserBundle\Entity\User:
        algorithm: bcrypt
        cost: 12

role_hierarchy:
    ROLE_ADMIN:       ROLE_USER
    ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]

providers:
    # in_memory:
    #     memory:
    #         users:
    #             user:  { password: userpass, roles: [ 'ROLE_USER' ] }
    #             admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }
    administrators:
        entity: { class: BrsUserBundle:User, property: fname }

firewalls:
    login: 
        pattern: ^/admin/login$
        anonymous: ~
    admin_area:
        pattern: ^/admin/
        # http_basic: ~
        form_login:
            login_path: /admin/login
            check_path: /admin/login_check

access_control:
    - { path: ^/admin/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/admin, roles: ROLE_ADMIN }

现在我的表单模板发布到 security.yml 中 form_login 下定义的 check_path。

我在 LoginBundle/config/routing.yml

中的包中定义了 2 条路由
admin:
    path: /admin/login
    defaults: { _controller: BrsLoginBundle:Login:index }

adminlogin:
    path: /admin/login_check
    defaults: { _controller: BrsLoginBundle:Login:loginCheck }

admin_hello:
    path: /admin/hello
    defaults: { _controller: BrsLoginBundle:Login:hello }

当我提交表格时,它会 return 我到 /admin/login/ url 我似乎无法通过它进行身份验证。

根据我在 LoginController.php 中的理解,symfony 2 文档告诉我定义方法 loginCheckAction(),它是空的,return什么都没有。

如果我正确地遵循了这一点,表单将发布到 login_check 路径,并且安全系统应该像我使用 http_basic 时一样处理身份验证。

我很困惑,我目前正在再次阅读文档,看看我是否遗漏了一些愚蠢的东西。

如有任何帮助,我们将不胜感激。

亚当

编辑*

这是呈现表单的树枝模板:

    {% extends 'BrsLoginBundle::layout.html.twig' %}

{% block body %}
       <h1>{{ name }}</h1>
{% if error %}
    <div>{{ error.messageKey|trans(error.messageData) }}</div>
{% endif %}       {#{form_start(form,{ 'attr': {'novalidate': 'novalidate' }})}#}
       <form action="{{ path('login_check')}}" method="post">
       <input type="text" name="_username" />
       <input type="password" name="_password" />
       <button type="submit">Login</button>
       </form>
       {#{form_widget(form)}#}
       {#{form_end(form)}#}
{% endblock %}

这里是控制器

<?php
    namespace Brs\LoginBundle\Controller;

    use Symfony\Bundle\FrameworkBundle\Controller\Controller;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\Response;
    use Brs\LoginBundle\Form\Type\LoginType;
    use Symfony\Component\Security\Core\SecurityContextInterface;


    class LoginController extends Controller{

        public function indexAction(Request $request){
            $session = $request->getSession();
            //instantiate the form type to use
            //$login = new LoginType();
            // create the form based on the type above
            //$form = $this->createForm(new LoginType(), $login);
            // this will tell me wether the form was submitted or not and handle the validation defined in bundle/resources/config/validation.yml
            //$form->handleRequest($request);
            //checks if the form is valid then we will execute what we want to next
            //if($form->isValid()){
                //do something if all validation test are passed        
            //} 
            var_dump($request->attributes->has(SecurityContextInterface::AUTHENTICATION_ERROR));
            var_dump($session->has(SecurityContextInterface::AUTHENTICATION_ERROR));
            var_dump(null !== $session);

            $error = $session->get(SecurityContextInterface::AUTHENTICATION_ERROR);
            $session->remove(SecurityContextInterface::AUTHENTICATION_ERROR);   
            //print_r($request->attributes->get(SecurityContextInterface::AUTHENTICATION_ERROR));
            //print_r($session->get(SecurityContextInterface::AUTHENTICATION_ERROR));
            //render the login template and pass the created form to it
            return $this->render('BrsLoginBundle:Admin:login.html.twig',array(
                'name'=>"Login",
                'error'=>$error
                //'form'=>$form->createView(),
            ));
        }

        public function hello(){
            return new Response("i shoudlnt be able to see this");
        }

        public function loginCheckAction(){

        }
    }
?>  

这是我一直关注的文档的link:

http://symfony.com/doc/2.3/cookbook/security/form_login_setup.html

编辑*

我已经跟踪了日志,这是对用户进行身份验证,但是当它调用 login_check 方法时,它会尝试从数据库重新加载用户,但找不到。所以它重新开始登录过程。日志位于下面的 link 中:

http://pastebin.com/sfTCNJS7

我猜是有错误

access_control:
    - { path: ^/admin/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/admin, roles: ROLE_ADMIN }

关于访问 /admin/* 路由,您告诉 symfony 用户必须已经过身份验证。此控制在 /admin/login_check 开始他的操作之前完成。

你应该修改security.yml如下

access_control:
    - { path: ^/admin/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/admin/login_check, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/admin, roles: ROLE_ADMIN }

编辑

OP 声称在注销后我无法再登录。我怀疑他注销背后的逻辑不好。如果您查看他的日志,您会注意到,在第二次登录尝试后,Symfony2 报告

[2015-02-17 14:57:16] security.WARNING: Username "" could not be found. [] []

好像没有用户名传递给 login_check 操作