doulvyi2172
2015-02-16 22:19
浏览 232
已采纳

Symfony 2.3自定义表单login_check

I have successfully created a login system that checks a doctrine user entity class and authenticates successfully. This uses http_basic which is set in the firewalls block in:

app/config/security.yml

However I wish to use the form_login option and render my own custom login template. Below is the app/config/security.yml after i made changes to use form login which renders my custom form:

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 }

Now my form template posts to the check_path defined under form_login in security.yml.

I have the 2 routes defined within the bundle in LoginBundle/config/routing.yml

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 }

When i submit the form it will return me to the /admin/login/ url and i cannot seem to get this to authenticate.

From my understanding in the LoginController.php the symfony 2 docs tell me to define the method loginCheckAction(), which is empty and returns nothing.

If i am following this correctly the form posts to the login_check path and the security system should handle the authentication just like when I used http_basic.

I am baffled and I am currently reading the docs again to see if i have missed something silly.

Any help would be greatly appreciated.

Adam

EDIT*

Here is the twig template that renders the form:

    {% 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 %}

here is the controller

<?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(){

        }
    }
?>  

Here is the link to the documentation that I have been following:

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

EDIT*

I have tailed the logs and this is Authenticating the user, However when it calls the login_check method , it then attempts to reload the user from the database but fails to find one. so it starts the login procedure over again. The logs are in the link below:

http://pastebin.com/sfTCNJS7

  • 写回答
  • 好问题 提建议
  • 追加酬金
  • 关注问题
  • 邀请回答

1条回答 默认 最新

  • douxing9813 2015-02-17 07:52
    最佳回答

    I suppose that error is there

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

    as to access /admin/* routes you're telling to symfony that user has to be already authenticated. This control is done before /admin/login_check starts his actions.

    You should modify security.yml as follows

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

    EDIT

    OP claims that after logout I can't login anymore. I suspect that his logic behind logout isn't good. If you take a look to his logs you can notice that, after second login attempt, Symfony2 reports

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

    like no username is passed to login_check action

    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题