Php Symfony:根据LDAP服务器对用户进行身份验证,但仅当其用户名位于自定义数据库表中时才允许登录
首先简要说明我的任务。我使用的是symfony2.8,有一个带有restapi和SonataAdminBundle的应用程序。网站访问者可以通过REST API发布某些数据,该API将持久化到数据库中。某一组员工应通过管理区管理这些数据 对管理区域的访问应使用用户名和密码进行保护。有一个实体Php Symfony:根据LDAP服务器对用户进行身份验证,但仅当其用户名位于自定义数据库表中时才允许登录,php,symfony,authentication,ldap,Php,Symfony,Authentication,Ldap,首先简要说明我的任务。我使用的是symfony2.8,有一个带有restapi和SonataAdminBundle的应用程序。网站访问者可以通过REST API发布某些数据,该API将持久化到数据库中。某一组员工应通过管理区管理这些数据 对管理区域的访问应使用用户名和密码进行保护。有一个实体Employee具有属性username,但没有密码。应针对LDAP服务器进行身份验证,但对管理区域的访问应仅限于实体Employee中存在的员工,即引用数据库表 对于LDAP身份验证,我使用Symfony
Employee
具有属性username
,但没有密码。应针对LDAP服务器进行身份验证,但对管理区域的访问应仅限于实体Employee
中存在的员工,即引用数据库表
对于LDAP身份验证,我使用Symfony 2.8中的新LDAP组件
除此之外,内存中应该有一个名为的管理员帐户
这就是我现在拥有的:
app/config/services.yml
app/config/security.yml
src/AppBundle/Entity/Employee.php
src/AppBundle/Security/DbUserProvider.php
然后,甚至不会调用方法loadUserByUsername
,所有用户都可以登录,包括数据库中的用户和非数据库中的用户
内存中的用户管理员在任何情况下都可以毫无问题地登录
谢谢你的帮助。如果有人认为我的整个方法不好,并且知道更好的方法,请不要吝惜批评
我知道有FOSUserBundle和SonataUserBundle,但我更喜欢自定义用户提供者,因为我不想让实体员工膨胀,因为我真的不需要所有这些属性,如密码、salt、isLocked等。此外,我不认为在我的特定情况下配置SonataUserBundle会简单得多。如果您仍然认为有更优雅的方式来完成这两个捆绑包的任务,我将非常感谢您的建议。您可以为每个防火墙配置用户检查器,您的db用户提供程序实际上不是用户提供程序,因为它不具备验证用户身份所需的所有信息(例如密码)
因此,我要做的是,我将删除db用户提供程序并添加一个用户检查器,而用户检查器的主要思想是在身份验证过程中添加额外的检查,在您的情况下,我们需要检查用户是否在employee表中
要实现这一点,您需要做三件事
实现UserCheckerInterfaceSymfony\Component\Security\Core\User\UserCheckerInterface
检查用户是否在employee表中,是否在checkPostAuth()方法中
将新用户检查器作为服务公开
services:
app.employee_user_checker:
class: Path\To\Class\EmployeeUserChecker
更改防火墙配置以使用新的用户检查器
security:
firewalls:
admin:
pattern: ^/admin
user_checker: app.employee_user_checker
#...
回答得很好!它很好地解释了正确的方法,并指出了我的方法的缺陷。还有一些小问题我必须解决,但现在我知道如何干扰登录检查过程。非常感谢你!
namespace AppBundle\Entity;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\EquatableInterface;
use Doctrine\ORM\Mapping as ORM;
class Employee implements UserInterface, EquatableInterface
{
// other properties
private $username;
// getters and setters for the other properties
public function getUsername()
{
return $this->username;
}
public function getRoles()
{
return array('ROLE_USER');
}
public function getPassword()
{
return null;
}
public function getSalt()
{
return null;
}
public function eraseCredentials()
{
}
public function isEqualTo(UserInterface $user)
{
if (!$user instanceof Employee) {
return false;
}
if ($this->username !== $user->getUsername()) {
return false;
}
return true;
}
}
<?php
namespace AppBundle\Security;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Doctrine\ORM\EntityManager;
use AppBundle\Entity\Employee;
class DbUserProvider implements UserProviderInterface
{
private $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
public function loadUserByUsername($username)
{
$repository = $this->em->getRepository('AppBundle:Employee');
$user = $repository->findOneByUsername($username);
if ($user) {
return new Employee();
}
throw new UsernameNotFoundException(
sprintf('Username "%s" does not exist.', $username)
);
}
public function refreshUser(UserInterface $user)
{
if (!$user instanceof Employee) {
throw new UnsupportedUserException(
sprintf('Instances of "%s" are not supported.', get_class($user))
);
}
return $this->loadUserByUsername($user->getUsername());
}
public function supportsClass($class)
{
return $class === 'AppBundle\Entity\Employee';
}
}
chain_provider:
chain:
providers: [app_users, db_user]
services:
app.employee_user_checker:
class: Path\To\Class\EmployeeUserChecker
security:
firewalls:
admin:
pattern: ^/admin
user_checker: app.employee_user_checker
#...