我需要在我的网站上创建一个基于Symfony2的身份验证系统。我跟着that tutorial(法语),解释了如何验证用户以及如何登录。问题是我的身份验证系统无法使用从头开始构建的用户实体,因为我的目的是重构网站而不改变数据库的结构。
这是我从数据库生成的用户实体。这有点棘手,因为我需要该类来实现UserInterface,所以我手动添加了getUsername,getSalt和eraseCredetials方法:
namespace GEAP\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
class User implements UserInterface {
private $login;
private $password;
private $lastname;
private $firstname;
private $roles;
private $restrictionsIp;
private $idPage;
public function __construct()
{
$this->idPage = new \Doctrine\Common\Collections\ArrayCollection();
}
public function getLogin()
{
return $this->login;
}
public function getUsername()
{
return $this->login;
}
public function setPassword($password)
{
$this->password = $password;
return $this;
}
public function getPassword()
{
return $this->password;
}
public function getSalt()
{
return "md5";
}
public function setLastname($lastname)
{
$this->lastname = $lastname;
return $this;
}
public function getLastname()
{
return $this->lastname;
}
public function setFirstname($firstname)
{
$this->firstname = $firstname;
return $this;
}
public function getFirstname()
{
return $this->firstname;
}
public function setRoles($roles)
{
$this->roles = $roles;
return $this;
}
public function getRoles()
{
return $this->roles;
}
public function setRestrictionsIp($restrictionsIp)
{
$this->restrictionsIp = $restrictionsIp;
return $this;
}
public function getRestrictionsIp()
{
return $this->restrictionsIp;
}
public function addIdPage(\GEAP\IntranetBundle\Entity\Pages $idPage)
{
$this->idPage[] = $idPage;
return $this;
}
public function removeIdPage(\GEAP\IntranetBundle\Entity\Pages $idPage)
{
$this->idPage->removeElement($idPage);
}
public function getIdPage()
{
return $this->idPage;
}
public function eraseCredentials() {}
}
这是我的security.yml:
# app/config/security.yml
security:
encoders:
Symfony\Component\Security\Core\User\User: plaintext
GEAP\UserBundle\Entity\User: md5
role_hierarchy:
ROLE_ADMIN: [ROLE_ENS, ROLE_ETU, ROLE_SEC]
ROLE_SUPER_ADMIN: [ROLE_ENS, ROLE_ETU, ROLE_SEC, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
in_memory:
memory:
users:
user_ens: { password: userpass, roles: [ 'ROLE_ENS' ] }
user_etu: { password: userpass, roles: [ 'ROLE_ETU' ] }
user_sec: { password: userpass, roles: [ 'ROLE_SEC' ] }
admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }
main:
entity: { class: GEAP\UserBundle\Entity\User, property: login }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main_login:
pattern: ^/$
anonymous: true
main:
pattern: ^/
anonymous: false
# provider: main
provider: in_memory
form_login:
login_path: login
check_path: login_check
always_use_default_target_path: true
default_target_path: /home
logout:
path: logout
target: /
access_control:
#- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
这是我的SecurityController:
namespace GEAP\UserBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\SecurityContext;
class SecurityController extends Controller {
public function loginAction(Request $request) {
// Si le visiteur est déjà identifié, on le redirige vers l'accueil
if ($this->get('security.context')->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
return $this->redirect($this->generateUrl('geap_intranet_customhomepage'));
}
$session = $request->getSession();
// On vérifie s'il y a des erreurs d'une précédente soumission du formulaire
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('GEAPUserBundle:Security:login.html.twig', array(
// Valeur du précédent nom d'utilisateur entré par l'internaute
'last_username' => $session->get(SecurityContext::LAST_USERNAME),
'error' => $error,
));
}
}
当我取消注释安全性时:firewalls:main:provider:main line,当我尝试使用我的凭据(在数据库中)登录我的网站时,会出现该错误消息:
凭据无效。
你知道问题的来源吗?
答案 0 :(得分:0)
我建议创建一个不同的编码器:
encoders:
Symfony\Component\Security\Core\User\User:
algorithm: sha1
iterations: 1
encode_as_base64: false
创建登录检查方法:
public function loginCheckAction(Request $request){
/** @var Session $session */
$session = $request->getSession();
$username = $request->get('_username');
$password = $request->get('_password');
$anonymousKey = uniqid();
$passwordEncoder = new Pbkdf2PasswordEncoder();
$inMemoryUserProvider = new InMemoryUserProvider();
$userChecker = new UserChecker();
$encoderFactory = new EncoderFactory(array(
'Symfony\Component\Security\Core\User\User' => $passwordEncoder
));
$authenticationProviders = array(
// validates AnonymousToken instances
new AnonymousAuthenticationProvider($anonymousKey),
// retrieve the user for a UsernamePasswordToken
new DaoAuthenticationProvider($inMemoryUserProvider, $userChecker, 'main', $encoderFactory)
);
$authenticationManager = new AuthenticationProviderManager($authenticationProviders);
$accessDecisionManager = new AccessDecisionManager([new RoleVoter('ROLE_ADMIN')]);
$securityContext = new SecurityContext($authenticationManager, $accessDecisionManager);
try {
$usernamePasswordToken = new UsernamePasswordToken($username, $password, 'main');
$authenticationManager->authenticate($usernamePasswordToken);
$securityContext->setToken($usernamePasswordToken);
if ($securityContext->isGranted('ROLE_ADMIN')) {
/** @var TokenStorage $tokenStorage */
$tokenStorage = $this->get('security.token_storage');
$tokenStorage->setToken($usernamePasswordToken);
return $this->redirectToRoute('index');
} else {
$session->getFlashBag()->add('error', 'Access denied. Invalid credentials');
}
} catch (BadCredentialsException $e) {
$session->getFlashBag()->add('error', 'Invalid username or password');
} catch (ProviderNotFoundException $e) {
$session->getFlashBag()->add('error', 'Provider could not be found');
}
return $this->redirectToRoute('login');
}