2

我在 Symfony 2.2.1 上有一个简单的登录系统,问题是何时进入安全区域是的,显示登录表单并输入用户并通过,但总是将我发送到/login页面,有时将我发送到/. 查看日志我得到以下信息

[2013-04-22 20:25:01] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\HttpKernel\EventListener\ProfilerListener::onKernelRequest". [] []
[2013-04-22 20:25:01] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Bundle\FrameworkBundle\EventListener\SessionListener::onKernelRequest". [] []
[2013-04-22 20:25:02] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\HttpKernel\EventListener\FragmentListener::onKernelRequest". [] []
[2013-04-22 20:25:02] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\HttpKernel\EventListener\RouterListener::onKernelRequest". [] []
[2013-04-22 20:25:02] request.INFO: Matched route "login_check" (parameters: "_route": "login_check") [] []
[2013-04-22 20:25:02] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\HttpKernel\EventListener\LocaleListener::onKernelRequest". [] []
[2013-04-22 20:25:02] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\Security\Http\Firewall::onKernelRequest". [] []
[2013-04-22 20:25:02] doctrine.DEBUG: SELECT t0.id AS id1, t0.nombre AS nombre2, t0.contrasena AS contrasena3, t0.salt AS salt4 FROM usuario t0 WHERE t0.nombre = ? LIMIT 1 ["rkmax"] []
[2013-04-22 20:25:02] doctrine.DEBUG: SELECT t0.id AS id1, t0.nombre AS nombre2 FROM rol t0 INNER JOIN usuario_rol ON t0.id = usuario_rol.rol_id WHERE usuario_rol.usuario_id = ? [8] []
[2013-04-22 20:25:02] security.INFO: User "" has been authenticated successfully [] []
...
[2013-04-22 20:25:02] security.WARNING: Username "" could not be found. [] []

如您所见,在 SecurityContext 中写入时用户为空,但我不知道原因。

课程和设置

class SecurityController extends Controller
{
    public function loginAction()
    {
        $request = $this->getRequest();
        $session = $request->getSession();

        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('MySecurityBundle:Security:login.html.twig', array(
            'last_username' => $session->get(SecurityContext::LAST_USERNAME),
            'error' => $error,
        ));
    }
}

两个实体Usuario(用户)和Rol(角色)都实现了与 symfony 安全对话的接口

class Rol implements RoleInterface

//Repository/Usuario
class Usuario extends EntityRepository implements UserProviderInterface
{
    public function loadUserByUsername($login)
    {
        $usuario = $this->findOneBy(array('nombre' => $login));

        if (!$usuario) {
            throw new UsernameNotFoundException(
                sprintf("El usuario '%s' no existe o el nombre esta mal escrito", $login)
            );
        }

        return $usuario;
    }

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

    public function supportsClass($class)
    {
        return $class === 'Iscltda\SecurityBundle\Entity\Usuario';
    }
}

class Usuario implements UserInterface, \Serializable
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="nombre", type="string", length=200, nullable=false)
     */
    private $nombre;

    /**
     * @var string
     *
     * @ORM\Column(name="contrasena", type="string", length=64, nullable=false)
     */
    private $contrasena;

    /**
     * @var string
     *
     * @ORM\Column(name="salt", type="string", length=64, nullable=false)
     */
    private $salt;

    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\ManyToMany(targetEntity="Rol", inversedBy="usuario")
     * @ORM\JoinTable(name="usuario_rol",
     *   joinColumns={
     *     @ORM\JoinColumn(name="usuario_id", referencedColumnName="id")
     *   },
     *   inverseJoinColumns={
     *     @ORM\JoinColumn(name="rol_id", referencedColumnName="id")
     *   }
     * )
     */
    private $rol;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->rol = new \Doctrine\Common\Collections\ArrayCollection();
    }

    public function __toString()
    {
        return $this->getNombre();
    }


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

    /**
     * Set nombre
     *
     * @param string $nombre
     * @return Usuario
     */
    public function setNombre($nombre)
    {
        $this->nombre = $nombre;

        return $this;
    }

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

    /**
     * Set contrasena
     *
     * @param string $contrasena
     * @return Usuario
     */
    public function setContrasena($contrasena)
    {
        $this->contrasena = $contrasena;

        return $this;
    }

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

    /**
     * Set salt
     *
     * @param string $salt
     * @return Usuario
     */
    public function setSalt($salt)
    {
        $this->salt = $salt;

        return $this;
    }

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

    /**
     * Add rol
     *
     * @param \Iscltda\SecurityBundle\Entity\Rol $rol
     * @return Usuario
     */
    public function addRol(\Iscltda\SecurityBundle\Entity\Rol $rol)
    {
        $this->rol[] = $rol;

        return $this;
    }

    /**
     * Remove rol
     *
     * @param \Iscltda\SecurityBundle\Entity\Rol $rol
     */
    public function removeRol(\Iscltda\SecurityBundle\Entity\Rol $rol)
    {
        $this->rol->removeElement($rol);
    }

    /**
     * Get rol
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getRol()
    {
        return $this->rol;
    }

    public function getRoles()
    {
        return $this->rol->toArray();
    }

    public function getPassword()
    {
        return $this->getContrasena();
    }

    public function getUsername()
    {
        $this->getNombre();
    }

    public function eraseCredentials()
    {

    }

    /**
     * Serializes the content of the current User object
     * @return string
     */
    public function serialize()
    {
        return \serialize(array(
            $this->id,
            $this->nombre,
            $this->salt,
            $this->contrasena
        ));
    }

    /**
     * Unserializes the given string in the current User object
     * @param serialized
     */
    public function unserialize($serialized)
    {
        list(
            $this->id,
            $this->nombre,
            $this->salt,
            $this->contrasena
        ) = \unserialize($serialized);
    }
}

routing.yml设置_

login:
    pattern: /admin/login
    defaults: { _controller: MySecurityBundle:Security:login }

login_check:
    pattern: /admin/login_check

logout:
    pattern: /admin/logout

这是我的security.yml设置

security:
    encoders:
        MyVendor\MySecurityBundle\Entity\Usuario:
            algorithm: sha256
            encode-as-base64: true
            iterations: 10

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

    providers:
        user_db:
            entity: { class: MyVendor\MySecurityBundle\Entity\Usuario, property: nombre }

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

        login:
            pattern:  ^/admin/login$
            security: false
            anonymous: ~

        secured_area:
            provider: user_db
            security: true
            pattern:    ^/admin
            form_login:
                login_path: /admin/login
                check_path: /admin/login_check
            logout:
                path:   /logout
                target: /

更新

我发现问题是我getUsername更改为的方法中没有返回任何内容

public function getUsername()
{
    return $this->getNombre();
}

但仍然将我发送到登录页面

更新 2

我在 UserProvider 类中发现了最后一个问题,该方法refreshUser是错误的,我已更改为

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

这可以正常工作

4

0 回答 0