我正在开展一个Symfony 4
项目。尝试登录后,它会使用匿名令牌将我重定向回登录页面。我的设置是使用symfony docs
的登录表单。点击登录后,我的会话只有csrf/authenticate
属性。
任何想法我做错了什么?
Security.yaml
security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
encoders:
App\Entity\User:
algorithm: bcrypt
providers:
in_memory: { memory: ~ }
db_provider:
entity:
class: App\Entity\User
role_hierarchy:
ROLE_MANAGER: ROLE_USER
ROLE_ADMIN: ROLE_MANAGER
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: ~
provider: db_provider
form_login:
login_path: login
check_path: login_check
csrf_token_generator: security.csrf.token_manager
default_target_path: index
always_use_default_target_path: true
# activate different ways to authenticate
# http_basic: true
# https://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate
# form_login: true
# https://symfony.com/doc/current/security/form_login_setup.html
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
- { path: ^/admin, roles: ROLE_ADMIN}
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY}
- { path: ^/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: ROLE_USER }
# - { path: ^/profile, roles: ROLE_USER }
framework.yaml
framework:
secret: '%env(APP_SECRET)%'
session:
handler_id: ~
save_path: '/tmp'
csrf_protection: ~
登录模板
{% extends 'base.html.twig' %}
{% block body %}
{% if error %}
<div> {{ dump() }}
{{ error.messageKey|trans(error.messageData, 'security') }}
{{ error.message }}
</div>
{% endif %}
{{ dump (request) }}
<form action="{{ path('login') }}" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="_username" value="{{ last_username }}"/>
<label for="password">Password:</label>
<input type="password" id="password" name="_password"/>
<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}"/>
<button type="submit">Login</button>
</form>
{% endblock %}
SecurityController
<?php
namespace App\Controller;
use App\Entity\User;
use App\Form\EditUserFormType;
use function ContainerNbSxonP\getSecurity_AuthorizationCheckerService;
use Couchbase\Authenticator;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
class SecurityController extends Controller {
/**
* @Route("/", name="index")
*/
public function index()
{
return $this->render('index.html.twig');
}
/**
* @Route("/login/", name="login")
*/
public function login(Request $request, AuthenticationUtils $authenticationUtils)
{
$session = $request->getSession();
print_r($_POST);
$error = $authenticationUtils->getLastAuthenticationError();
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('Security/login.html.twig', array(
'last_username' => $lastUsername,
'error' => $error,
'request' => $session
));
}
/**
* @Route("/login_check", name="login_check")
*/
public function login_check()
{
}
}
user.php的
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity(repositoryClass="App\Repository\UserRepository")
* @UniqueEntity(fields="email", message="Email already taken")
* @UniqueEntity(fields="username", message="Username already taken")
*/
class User implements UserInterface, \Serializable
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=191, unique=true)
* @Assert\NotBlank()
*/
private $username;
/**
* @ORM\Column(type="string", length=191, unique=true)
* @Assert\NotBlank()
* @Assert\Email()
*/
private $email;
/**
* @Assert\NotBlank()
* @Assert\Length(max=4096)
*/
private $plainPassword;
/**
* @ORM\Column(type="string", length=64)
*/
private $password;
/**
* @ORM\Column(type="array")
*/
private $roles;
public function getId()
{
return $this->id;
}
public function getUsername(): ?string
{
return $this->username;
}
public function setUsername(string $username): self
{
$this->username = $username;
return $this;
}
public function getEmail()
{
return $this->email;
}
public function setEmail(string $email) :self
{
$this->email = $email;
return $this;
}
public function getPlainPassword()
{
return $this->plainPassword;
}
public function setPlainPassword($password)
{
$this->plainPassword = $password;
}
public function getPassword(): ?string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
/**
* Returns the roles granted to the user.
*
* <code>
* public function getRoles()
* {
* return array('ROLE_USER');
* }
* </code>
*
* Alternatively, the roles might be stored on a ``roles`` property,
* and populated in any number of different ways when the user object
* is created.
*
* @return (Role|string)[] The user roles
*/
public function getRoles()
{
$roles = $this->roles;
// give everyone ROLE_USER!
if (!in_array('ROLE_USER', $roles)) {
$roles[] = 'ROLE_USER';
}
return $roles;
}
public function setRoles(array $roles)
{
$this->roles = $roles;
}
/**
* Returns the salt that was originally used to encode the password.
*
* This can return null if the password was not encoded using a salt.
*
* @return string|null The salt
*/
public function getSalt()
{
return null;
}
/**
* Removes sensitive data from the user.
*
* This is important if, at any given point, sensitive information like
* the plain-text password is stored on this object.
*/
public function eraseCredentials()
{
// TODO: Implement eraseCredentials() method.
}
/**
* String representation of object
* @link http://php.net/manual/en/serializable.serialize.php
* @return string the string representation of the object or null
* @since 5.1.0
*/
/** @see \Serializable::serialize() */
public function serialize()
{
return serialize(array(
$this->id,
$this->username,
$this->password,
));
}
/** @see \Serializable::unserialize()
* @param $serialized
*/
public function unserialize($serialized)
{
var_dump($serialized);
list (
$this->id,
$this->username,
$this->password,
) = unserialize($serialized);
}
}
dev.log
[2018-03-29 11:54:08] request.INFO: Matched route "login". {"route":"login","route_parameters":{"_controller":"App\\Controller\\SecurityController::login","_route":"login"},"request_uri":"http://helper/login/","method":"POST"} []
[2018-03-29 11:54:08] security.INFO: Populated the TokenStorage with an anonymous Token. [] []
[2018-03-29 11:54:08] request.INFO: Matched route "_wdt". {"route":"_wdt","route_parameters":{"_controller":"web_profiler.controller.profiler:toolbarAction","token":"e2a230","_route":"_wdt"},"request_uri":"http://helper/_wdt/e2a230","method":"GET"} []
[2018-03-29 11:54:11] request.INFO: Matched route "_profiler". {"route":"_profiler","route_parameters":{"_controller":"web_profiler.controller.profiler:panelAction","token":"e2a230","_route":"_profiler"},"request_uri":"http://helper/_profiler/e2a230?panel=request","method":"GET"} []
[2018-03-29 11:54:11] request.INFO: Matched route "_profiler_search_bar". {"route":"_profiler_search_bar","route_parameters":{"_controller":"web_profiler.controller.profiler:searchBarAction","_route":"_profiler_search_bar"},"request_uri":"http://helper/_profiler/search_bar?panel=request","method":"GET"} []
登录后会话转储
Session {#1549 ▼
#storage: NativeSessionStorage {#1550 ▼
#bags: array:2 [▼
"attributes" => SessionBagProxy {#1623 ▼
-bag: AttributeBag {#1608 ▼
-name: "attributes"
-storageKey: "_sf2_attributes"
#attributes: &1 array:2 [▶]
}
-data: &2 array:2 [▶]
-hasBeenStarted: &4 true
}
"flashes" => SessionBagProxy {#1624 ▼
-bag: FlashBag {#1609 ▼
-name: "flashes"
-flashes: &3 []
-storageKey: "_symfony_flashes"
}
-data: &2 array:2 [▼
"_sf2_attributes" => &1 array:2 [▼
"_csrf/authenticate" =>
"x6_X_CknVoh13DWDOWOIxGOnaxdyr_vTQbp9iQW3j-E"
"_security.main.target_path" => "http://helper/"
]
"_symfony_flashes" => &3 []
]
-hasBeenStarted: &4 true
}
]
#started: true
#closed: false
#saveHandler: SessionHandlerProxy {#1579 ▼
#handler: StrictSessionHandler {#1606 ▼
-handler: SessionHandler {#1607}
-doDestroy: null
-sessionName: "PHPSESSID"
-prefetchId: null
-prefetchData: null
-newSessionId: null
-igbinaryEmptyData: null
}
#wrapper: false
#saveHandlerName: "user"
}
#metadataBag: MetadataBag {#1551 ▼
-name: "__metadata"
-storageKey: "_sf2_meta"
#meta: & array:3 [▼
"u" => 1522332857
"c" => 1522314558
"l" => "0"
]
-lastUsed: 1522332823
-updateThreshold: 0
}
}
-flashName: "flashes"
-attributeName: "attributes"
-data: &2 array:2 [▶]
-hasBeenStarted: &4 true
}