2013-12-08 58 views
4

我正在使用FOSUserBundle開發symfony應用程序。如果我沒有通過身份驗證,我希望在菜單欄中有一個下拉式登錄表單,它具有與/ login下的完全不同的樣式。我自己的登錄表單上的無效CSRF令牌

我收到'無效的CSRF令牌'。我是一個symfony2的新手,所以也許我犯了一個明顯的錯誤,但是我找不到解決方法。這是我的嘗試:

控制器:

<?php 

namespace RoiRodriguez\CustomUserBundle\Controller; 

use Symfony\Bundle\FrameworkBundle\Controller\Controller; 
use Symfony\Component\Routing\Annotation\Route; 
use Symfony\Component\Security\Core\SecurityContext; 

class DefaultController extends Controller { 

    /** 
    * Para requests internos, renderiza la barra de navegación. 
    * No tiene ruta. 
    */ 
    public function navigationAction() { 
     $params = array (
       'csrf_token' => '', 
       'last_username' => '' 
     ); 

     if ($this->container->get ('security.context')->isGranted ('IS_AUTHENTICATED_FULLY')) { 
      $session = $this->getRequest()->getSession(); 
      $params ['last_username'] = (null === $session) ? '' : $session->get (SecurityContext::LAST_USERNAME); 
      $params ['csrf_token'] = $this->container->get ('form.csrf_provider')->generateCsrfToken ('authenticate'); 
     } 

     return $this->render ('CustomUserBundle:Default:navigation.html.twig', $params); 
    } 
} 

查看:

<ul class="nav navbar-nav navbar-right"> 
{% if app.user and app.user.isGranted('IS_AUTHENTICATED_FULLY') %} 
    {% include 'CustomUserBundle:Default:includes/navigation-authenticated.html.twig' %} 
{% else %} 
    {% include 'CustomUserBundle:Default:includes/navigation-notauthenticated.html.twig' with {'csrf_token': csrf_token, 'last_username': last_username} %} 
{% endif %} 
</ul> 

未通過身份驗證模板:

<li><a href="{{ path('fos_user_registration_register') }}">Nueva cuenta</a></li> 
<li class="dropdown"><a href="#" class="dropdown-toggle" 
    data-toggle="dropdown">Ingresar <b class="caret"></b></a> 
    <div class="dropdown-menu dd-login-form-container"> 

     <!-- login form --> 
     <form role="form" method="post" 
      action="{{ path("fos_user_security_check") }}"> 
      <input type="hidden" name="_csrf_token" value="{{ csrf_token }}" /> 
...... 
      <button type="submit" class="btn btn-primary">Ingresa!</button> 
     </form> 
     <!-- end login form --> 
     <ul> 
      <li><a href="{{ path('fos_user_resetting_request') }}">¿Has olvidado 
        tu contraseña?</a></li> 
      <li><a href="{{ path('fos_user_registration_register') }}">¿Todavía 
        no tienes una cuenta?</a></li> 
     </ul> 
    </div> 
</li> 

我在想什麼?另外:這個下拉菜單也得到渲染內/登錄,我會有任何麻煩生成令牌兩次?

+0

我非常新的Symfony的,但你可以嘗試設置csrf_token爲假,可能是它會奏效。 –

回答

1

@Roirodriguez,你的代碼可以幫助我解決這個問題。我想你只需要調用渲染方法而不是包含(我的第4步)。

我想在我的標題上做一個簡單的登錄表單,如果發生任何錯誤,它會將您重定向到提供反饋的FOSUserBundle正常登錄頁面。用戶在通過身份驗證後,我想用的用戶名,打開的時候更多的選擇會showup(註銷鏈接等)下拉

這裏是我設法得到它的工作:

  1. 創建一個FOSUserBundle的兒童套裝。我創建了一個新的包名稱UserBundle,然後使用get父級方法。 link to FOSUserBundle docs

    <?php 
    namespace Me\UserBundle; 
    use Symfony\Component\HttpKernel\Bundle\Bundle; 
    class MeUserBundle extends Bundle 
    { 
        public function getParent() 
        { 
         return 'FOSUserBundle'; 
        } 
    } 
    
  2. 創建模板創造了這個新的登錄表單的新模板,並通過身份驗證的下拉

    {#loginHorizontal.html.twig#} 
    
    {% trans_default_domain 'FOSUserBundle' %} 
    <div class="nav navbar-nav navbar-right"> 
    <form class="navbar-form navbar-left form-inline" action="{{ path("fos_user_security_check") }}" method="post" role="form" > 
        <input type="hidden" name="_csrf_token" value="{{ csrf_token }}" /> 
        <div class="form-group"> 
         <div class="input-group"> 
          <div class="input-group-addon"><i class="fa fa-user" ></i></div> 
          <input type="text" class="form-control" id="txt_username" 
            placeholder="{{ 'security.login.username'|trans }}" name="_username" 
            value="{{ last_username }}" required="required" > 
         </div> 
        </div> 
        <div class="form-group"> 
         <div class="input-group"> 
          <div class="input-group-addon"><i class="fa fa-asterisk" ></i></div> 
          <input type="password" class="form-control" id="txt_pwd" name="_password" required="required" placeholder="{{ 'security.login.password'|trans }}" /> 
         </div> 
    
        </div> 
        <input type="submit" id="_submit" name="_submit" class="btn btn-primary" value="{{ 'security.login.submit'|trans }}" /> 
        <br /> 
        <div class="checkbox"> 
         <label> 
          <input type="checkbox" id="remember_me" name="_remember_me" value="on" /> {{ 'security.login.remember_me'|trans }} 
         </label> 
        </div> 
    </form> 
    </div> 
    
    
    
    {#authenticadedDropdown.html.twig#} 
    
    {% trans_default_domain 'FOSUserBundle' %} 
    <ul class="nav navbar-nav navbar-right" > 
        <li class="dropdown"> 
         <a href="#" class="dropdown-toggle" data-toggle="dropdown"> welcome, {{ app.user.username }}<span class="caret"></span></a> 
         <ul class="dropdown-menu" role="menu"> 
          <li><a href="#">bla bla</a></li> 
          <li class="divider"></li> 
          <li><a href="{{ path('fos_user_security_logout') }}"> 
           {{ 'layout.logout'|trans({}, 'FOSUserBundle') }} 
          </a></li> 
         </ul> 
        </li> 
        <li></li> 
    </ul> 
    
  3. Overided的SecurityController和創造行動在此改變控制器和創建一個新的動作該模板創建併發送變量csrf_token &用戶名作爲登錄參數。

    namespace Me\UserBundle\Controller; 
    
    use FOS\UserBundle\Controller\SecurityController as BaseController; 
    use Symfony\Component\HttpFoundation\Request; 
    use Symfony\Component\Security\Core\SecurityContextInterface; 
    
    
    class SecurityController extends BaseController 
    { 
        /** 
        * For internal template use: Renders the Horizontal Login ej. Header bar login. 
        * No routing used. 
        */ 
        public function loginHorizontalAction(Request $request) 
        { 
         /** @var $session \Symfony\Component\HttpFoundation\Session\Session */ 
         $session = $request->getSession(); 
    
         // last username entered by the user 
         $lastUsername = (null === $session) ? '' : $session->get(SecurityContextInterface::LAST_USERNAME); 
    
         $csrfToken = $this->container->has('form.csrf_provider') 
          ? $this->container->get('form.csrf_provider')->generateCsrfToken('authenticate') 
          : null; 
    
         $data = array(
          'last_username' => $lastUsername, 
          'csrf_token' => $csrfToken, 
         ); 
         return $this->container->get('templating')->renderResponse('MeUserBundle:Security:loginHorizontal.html.twig', $data); 
        } 
    
        /** 
        * For internal template use: Renders the Dropdown after authentication ej. Header bar for user. 
        * No routing used. 
        */ 
        public function authenticatedDropdownAction() 
        { 
         $data = array(); 
         return $this->container->get('templating') 
          ->renderResponse('MeUserBundle:Security:authenticatedDropdown.html.twig', $data); 
        } 
    } 
    
  4. 嵌入控制器動作最後我通過樹枝模板嵌入式/ renderes這個新創建的控制器的作用Symfony doc on how to embed controller actions

    <div class="navbar-right" > 
        {% block login %} 
         {% if is_granted("IS_AUTHENTICATED_REMEMBERED") %} 
          {% render(controller("MeUserBundle:Security:authenticatedDropdown")) %} 
         {% else %} 
          {% render(controller("MeUserBundle:Security:loginHorizontal")) %} 
         {% endif %} 
        {% endblock %} 
    </div> 
    

我知道這是自您的帖子,同時,但希望這有助於。

乾杯, 潘喬

4

我的自定義登錄表單是給我同樣的問題, - '無效的CSRF令牌' - 任何時候我嘗試登錄。在閱讀FOSUserBundle配置選項(FOSUserBundle Configuration Reference)的文檔後,我發現該軟件包默認啓用了不同的令牌管理器。所以我去了我的security.yml文件並註釋掉了爲登錄表單指定一個csrf標記生成器的行。

下面是我的app/config/security.yml文件的一個截面,其中指定了crsf標記管理器註釋的配置。

security: 

....... 

firewalls: 

    ........ 

    vendor: 
     pattern: ^/vendor 
     form_login: 
      provider: fos_userbundle 
     # csrf_token_generator: security.csrf.token_manager 
      login_path: vendor_login 
      check_path: vendor_login_check 
     logout: true 

這樣做了以後,我的登錄表單開始工作,我可以登錄。