我有一個基於Symfony2的項目,我自己編碼驗證(基於文檔和食譜)。該項目有兩種類型的用戶:一些用LDAP認證,其他用戶用數據庫憑證。 問題是,如果有更多的用戶登錄他們的會話頻繁丟失(5分鐘或更少),他們需要再次登錄(目前我在開發環境)。 有什麼我可以做錯了(雖然我不這麼認爲),或者這是一個Symfony2錯誤或PHP設置造成這種情況? 任何幫助深表謝意。Symfony2經常失敗登錄
監聽器:
class LdapListener implements ListenerInterface
{
protected $tokenStorage;
protected $authenticationManager;
public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager)
{
$this->tokenStorage = $tokenStorage;
$this->authenticationManager = $authenticationManager;
}
public function handle(GetResponseEvent $event)
{
$request = $event->getRequest();
$username = $request->request->get('_username');
$password = $request->request->get('_password');
if ($username == null OR $password == null)
{
return;
}
$token = new LdapUserToken();
$token->setUser($username);
$token->setPassword($password);
try
{
$authenticationToken = $this->authenticationManager->authenticate($token);
$this->tokenStorage->setToken($authenticationToken);
}
catch (AuthenticationException $exception)
{
throw new AuthenticationException('Denied');
}
return;
}
}
身份驗證提供:
class LdapProvider implements AuthenticationProviderInterface {
private $userProvider;
private $em;
const ENC_KEY = 'SECRETKEY';
public function __construct(UserProviderInterface $userProvider, $doctrine) {
$this->em = $doctrine->getManager();
$this->userProvider = $userProvider;
}
public function authenticate(TokenInterface $token) {
$user = $this->userProvider->loadUserByUsername($token->getUsername());
if ($user && $user->getDomainUser() && $this->validateCredentials(
$token->getUsername(),
$token->getPassword()
)
) {
if ($token->getPassword() != '') {
$savePwd = $this->em->getRepository('LoginProfileBundle:LdapUser')->find($user->getId());
$savePwd->setMailPassword($this->encrypt($token->getPassword()));
$savePwd->setLastLogin(new \DateTime());
$this->em->persist($savePwd);
$this->em->flush();
}
$authenticatedToken = new LdapUserToken($user->getRoles());
$authenticatedToken->setUser($user);
return $authenticatedToken;
}
elseif ($user && trim($token->getPassword()) == trim($this->decrypt($user->getRealPassword()))) {
if ($token->getPassword() != '') {
$savePwd = $this->em->getRepository('LoginProfileBundle:LdapUser')->find($user->getId());
$savePwd->setLastLogin(new \DateTime());
$this->em->persist($savePwd);
$this->em->flush();
}
$authenticatedToken = new LdapUserToken($user->getRoles());
$authenticatedToken->setUser($user);
return $authenticatedToken;
}
throw new AuthenticationException('LdapProvider: Invalid login details');
}
public function encrypt($pure_string) {
$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$encrypted_string = mcrypt_encrypt(
MCRYPT_BLOWFISH,
self::ENC_KEY,
utf8_encode($pure_string),
MCRYPT_MODE_ECB,
$iv
);
return base64_encode($encrypted_string);
}
public function decrypt($encrypted_string) {
if (trim($encrypted_string) == '' || $encrypted_string == null) {
return 'n';
}
$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$encrypted_string = base64_decode($encrypted_string);
$decrypted_string = mcrypt_decrypt(MCRYPT_BLOWFISH, self::ENC_KEY, $encrypted_string, MCRYPT_MODE_ECB, $iv);
return $decrypted_string;
}
public function supports(TokenInterface $token) {
return $token instanceof LdapUserToken;
}
public function validateCredentials($username, $password) {
$this->ldapLink = ldap_connect('SOMESERVERNAME');
if (!$this->ldapLink) {
return false;
}
ldap_set_option($this->ldapLink, LDAP_OPT_PROTOCOL_VERSION, 3);
if ([email protected]_bind($this->ldapLink, $username, $password)) {
return null;
}
else {
return true;
}
}
}
令牌:
class LdapUserToken extends AbstractToken {
private $password;
public function __construct(array $roles = array()) {
parent::__construct($roles);
$this->setAuthenticated(count($roles) > 0);
}
public function getCredentials() {
return '';
}
public function setPassword($password) {
$this->password = $password;
}
public function getPassword() {
return $this->password;
}
}
Security.yml
security:
encoders:
Login\ProfileBundle\Entity\LdapUser: plaintext
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_SUPER_ADMIN, ROLE_ADMIN]
providers:
in_domain:
entity:
class: Login\ProfileBundle\Entity\LdapUser
property: username
firewalls:
default:
anonymous: ~
http_basic: ~
ldap: true
provider: in_domain
form_login:
login_path: /login
check_path: /login_check
logout:
path: /logout
target: /login
switch_user: true
access_control:
- { path: ^/_wdt, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: ROLE_USER }
配置:
services:
twig.extension.intl:
class: Twig_Extensions_Extension_Intl
tags:
- { name: twig.extension }
ldap.security.authentication.provider:
class: Login\ProfileBundle\Security\Authentication\Provider\LdapProvider
arguments: ["", "@doctrine"]
ldap.security.authentication.listener:
class: Login\ProfileBundle\Security\Firewall\LdapListener
arguments: ["@security.token_storage", "@security.authentication.manager"]
ldap_user_provider:
class: Login\ProfileBundle\Security\User\LdapUserProvider
聽起來像我這樣的會話配置問題。也許[垃圾收集器](http:// php。net/manual/en/session.configuration.php)踢得更快?我想到的另一件事是,Symfony應用程序和LDAP服務器之間的連接可能會下降,因此您的用戶詳細信息不能從數據庫中加載,這會導致Symfony將您視爲來賓用戶? – tftd
垃圾回收的速度與登錄人數有關嗎?如果我是唯一登錄會話的人幾乎有效。如果另外2-3-4個用戶上線,他們需要在幾分鐘後重新登錄.....這也發生在非LDAP用戶身上。 –
在這種情況下,我不知道可能會出現什麼問題。我一直在使用[這個包](https://packagist.org/packages/imag/ldap-bundle)進行LDAP身份驗證,並使用postgres數據庫進行身份驗證。到目前爲止我還沒有遇到任何問題。這可能是你的實現? – tftd