2012-04-09 33 views
0

這是我的實體:Symfony的2 SecurityBundle認證通過登錄表單提出BadCredentialsException

<?php 

namespace Trade\TradeBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 
use Symfony\Component\Validator\Constraints as Assert; 
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; 
use Symfony\Component\Security\Core\User\UserInterface; 

/** 
* @ORM\Entity(repositoryClass = "Trade\TradeBundle\Repository\UserRepository") 
* @ORM\Table(name = "user") 
* @UniqueEntity(fields = "username", message = "The username already exists.") 
*/ 
class User implements UserInterface 
{ 
/** 
* @ORM\id 
* @ORM\Column(name = "id", type = "integer") 
* @ORM\GeneratedValue(strategy = "AUTO") 
*/ 
protected $id; 

/** 
* @ORM\Column(name = "username", type = "string", length = 20, unique = true) 
* 
* @Assert\NotBlank(
*  message = "The username cannot be blank." 
*) 
*/ 
protected $username; 

/** 
* @ORM\Column(name = "password", type = "string", length = 40) 
* 
* @Assert\NotBlank(
*  message = "The password cannot be blank." 
*) 
* @Assert\MinLength(
*  limit = 8, 
*  message = "The password '{{ value }}' is too short. It should have {{ limit }} characters or more." 
*) 
* @Assert\MaxLength(
*  limit = 16, 
*  message = "The password '{{ value }}' is too long. It should have {{ limit }} characters or less." 
*) 
*/ 
protected $password; 

/** 
* @ORM\Column(type = "string", length = 40) 
*/ 
protected $salt; 

public function __construct() 
{ 
    $this->salt = md5(uniqid(null, true)); 
} 

/** 
* Get id 
* 
* @return integer 
*/ 
public function getId() 
{ 
    return $this->id; 
} 

/** 
* Set username 
* 
* @param string $username 
*/ 
public function setUsername($username) 
{ 
    $this->username = $username; 
} 

/** 
* Get username 
* 
* @return string 
*/ 
public function getUsername() 
{ 
    return $this->username; 
} 

/** 
* Set password 
* 
* @param string $password 
*/ 
public function setPassword($password) 
{ 
    $this->password = $password; 
} 

/** 
* Get password 
* 
* @return string 
*/ 
public function getPassword() 
{ 
    return $this->password; 
} 

public function getSalt() 
{ 
    return $this->salt; 
} 

public function getRoles() 
{ 
    return array('ROLE_USER'); 
} 

public function eraseCredentials() 
{ 
} 

public function equals(UserInterface $user) 
{ 
    return $this->username === $user->getUsername(); 
} 
} 

這是我的倉庫:

<?php 

namespace Trade\TradeBundle\Repository; 

use Doctrine\ORM\EntityRepository; 
use Symfony\Component\Security\Core\User\UserProviderInterface; 
use Symfony\Component\Security\Core\User\UserInterface; 

/** 
* UserRepository 
* 
* This class was generated by the Doctrine ORM. Add your own custom 
* repository methods below. 
*/ 
class UserRepository extends EntityRepository implements UserProviderInterface 
{ 
public function loadUserByUsername($username) 
{ 
    return $this->getEntityManager()->findOneByUsername($username); 
} 

public function refreshUser(UserInterface $user) 
{ 
    return $this->loadUserByUsername($user->getUsername()); 
} 

public function supportsClass($class) 
{ 
    return $class === 'Trade\TradeBundle\Entity\User'; 
} 
} 

這是security.yml:

security: 
    encoders: 
     Trade\TradeBundle\Entity\User: 
      algorithm: sha1 
      encode_as_base64: false 
      iterations: 1 

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

providers: 
    main: 
     entity: { class: TradeTradeBundle:User, property: username } 

firewalls: 
    dev: 
     pattern: ^/(_(profiler|wdt)|css|images|js)/ 
     security: false 

    secured_area: 
     pattern: ^/ 
     form_login: 
      check_path: /account/signin_check 
      login_path: /account/signin 
     logout: 
      path: /account/signout 
      target:/
     anonymous: ~ 

access_control: 
    - { path: ^/account/signin, roles: IS_AUTHENTICATED_ANONYMOUSLY } 
    - { path: ^/account, roles: ROLE_USER } 
    - { path: ^/admin, roles: ROLE_ADMIN } 

這是我的控制器操作:

/** 
* @Route("/account/signin", name = "account_signin") 
* @Route("/account/signin_check", name = "account_signin_check") 
* @Method({"GET", "POST"}) 
*/ 
public function signInAction() 
{ 
    $request = $this->getRequest(); 
    $session = $request->getSession(); 

    $user = new \Trade\TradeBundle\Entity\User(); 
    $form = $this->createForm(new \Trade\TradeBundle\Form\Type\UserType(), $user); 

    if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) 
    { 
     $error = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR); 
    } 
    else 
    { 
     $error = $session->get(SecurityContext::AUTHENTICATION_ERROR); 
     $session->remove(SecurityContext::AUTHENTICATION_ERROR); 
    } 

    return $this->render('TradeTradeBundle:Account:signin.html.twig', array('form' => $form->createView(), 'error' => $error)); 
} 

這是我的Form類:

<?php 

namespace Trade\TradeBundle\Form\Type; 

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilder; 


class UserType extends AbstractType 
{ 
public function buildForm(FormBuilder $builder, array $options) 
{ 
    $builder->add('username', 'text', array('required' => false)); 
    $builder->add('password', 'password', array('required' => false)); 
} 

public function getName() 
{ 
    return 'user'; 
} 

public function getDefaultOptions(array $options) 
{ 
    return array(
     'data_class' => 'Trade\TradeBundle\Entity\User' 
    ); 
} 
} 

這是我的方式:

{% if error %} 
    <div class="alert alert-error">{{ error }}</div> 
{% endif %} 
<form action="{{ path('account_signin_check') }}" method="post" class="form-inline" novalidate> 
    <table class="table"> 
     <tr> 
      <td style="width: 120px;">{{ form_label(form.username) }} <span class="required">*</span></td> 
      <td style="width: 220px;">{{ form_widget(form.username, { 'attr': {'placeholder': 'Username'} }) }}</td> 
      <td class="form-error" id="email_error">{{ form_errors(form.username) }}</td> 
     </tr> 
     <tr> 
      <td>{{ form_label(form.password) }} <span class="required">*</span></td> 
      <td>{{ form_widget(form.password, { 'attr': {'placeholder': 'Password'} }) }}</td> 
      <td class="form-error" id="password_error">{{ form_errors(form.password) }}</td> 
     </tr> 
     <tr> 
      <td colspan="2" style="text-align: right;"> 
       {{ form_rest(form) }} 
       <input type="reset" value="Cancel" class="btn" /> 
       <input type="submit" value="Sign in" class="btn btn-danger" /> 
      </td> 
     <td>&nbsp;</td> 
     </tr> 
    </table> 
</form> 

當我嘗試登錄,BadCredentialsException所示。我不知道爲什麼。根據Symfony的文檔,我認爲我做了一切正確的請求,幫助。

回答

1

像這樣_username和_password輸入名字或你的security.yml試試把這個下secured_area

​​

也許它可以幫助你!

0

這是相當古老的,但我希望我的回答可以幫助別人。

我得到了完全相同的問題,試圖將表單組件的用法和安全性混合使用。

不幸的是這不可能,因爲安全組件依賴於輸入表「名稱」參數(名稱的HTML定義)_username並調用login_check功能時_password。這不能用表單組件定義(無法定義輸入元素的這個可選參數)。

當給一個名稱元素與

- >添加(「MY_NAME」,...

其實這是通知,而不是元素的ID參數「name」參數buidlForm函數給出的「name」將是「somename [my_name]」(其中somename是Form類的getName()函數返回的值),不能是「_username」安全組件

也許一個解決方法將在安全定義文件中將username_parameter定義爲「somename [my_name]」,以便組件查找它,但是我甚至沒有嘗試過,因爲這是非常討厭的黑客行爲。

編輯: 其實一個我用另外一個問題的另一個解決方法是在Form類的getName()函數返回一個空字符串,所以我們得到:「MY_NAME」作爲輸入元素屬性,而不是「somename [MY_NAME ]」。 所以,也許我們可以嘗試給名稱屬性提供「_username」和「_password」值(還沒有嘗試過)。