我正在嘗試在我的 Symfony 應用程式中實作一個簡單的 LDAP 身份驗證。
應首先針對 LDAP 對用戶進行身份驗證,從而應從資料庫回傳自定義用戶物體。
如果用戶不在資料庫中但可以成功通過身份驗證,我想創建用戶。
除了在資料庫中自動創建用戶外,它到目前為止都有效。
providers:
users_db:
entity:
# the class of the entity that represents users
class: 'App\Entity\User'
# the property to query by - e.g. email, username, etc
property: 'username'
users_ldap:
ldap:
service: Symfony\Component\Ldap\Ldap
base_dn: '%env(LDAP_BASE_DN)%'
search_dn: '%env(LDAP_SEARCH_DN)%'
search_password: '%env(LDAP_SEARCH_PASSWORD)%'
default_roles: ROLE_USER
uid_key: uid
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
lazy: true
provider: users_db
http_basic_ldap:
service: Symfony\Component\Ldap\Ldap
dn_string: '%env(LDAP_DN_STRING)%'
通過上述配置,身份驗證針對 LDAP 運行,但用戶來自資料庫。因此,如果我沒有創建相應的用戶,登錄嘗試將不起作用。
我已經嘗試通過UserChecker、UserProvider和LoginEventListener(監聽事件onAuthenticationSuccess)自動創建用戶,不幸的是沒有成功。
onAuthenticationSuccess 事件僅在身份驗證成功后呼叫,因此不能在上述配置中使用,因為 users_db 提供程式(還)不包含用戶,即使 LDAP Basic 身份驗證有效。
然后我嘗試使用UserChecker和鏈式提供程式[users_ldap, users_db]。這也被執行了,但是我不再得到一個用戶物件,而是一個 LDAP 用戶。所以我嘗試創建自己的 UserProvider,不幸的是沒有成功。
如果有人知道這樣做的好方法,我將不勝感激回答或簡短評論。謝謝!
uj5u.com熱心網友回復:
我以前遇到過你的問題,我無法將他們的資訊自動保存在我的本地資料庫中,所以我按照以下步驟操作:
- 使用 cas auth 和 Ldap 作為用戶提供程式登錄。
- 重定向它們以在欄位中形成并檢索它們,如下所示:
<div>
{{ form_row(user_form.uid, { label: 'UID :*',
required: 'true',
attr: {
value : app.user.uid,
readonly: true
}
}) }}
</div>
- 提交表單后,他們的角色將從“ROLE_VISIT”更改為“ROLE_USER”,所有 LDAP 資訊都將保存在我的本地資料庫中。
- 您可以像這樣私下保存一些資料:
<div class="invisible" >
{{ form_row(user_form.genre,{
attr: { value : app.user.supannCivilite }
}) }}
</div>
我正在將此捆綁包用于LDAP,所以如果您需要任何幫助,請告訴我!
另外,你可以看看我的安全配置如下,希望它有用:
providers:
chain_provider:
chain:
providers: [in_memory, database, ldap]
in_memory:
memory:
users:
__NO_USER__:
password:
roles: ROLE_ANON
database:
entity:
class: App\Entity\User
property: uid
ldap:
id: ldap_user_provider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
l3_firewall:
pattern: ^/
provider: chain_provider
security: true
guard:
authenticators:
- cas.security.authentication.authenticator
logout:
path: /logout
success_handler: authentication_handler
invalidate_session: false
access_denied_handler: App\EventListener\AccessDeniedListener
main:
pattern: ^/
security: true
lazy: true
provider: chain_provider
guard:
authenticators:
- cas.security.authentication.authenticator
uj5u.com熱心網友回復:
感謝這個答案,我現在開始作業了。
配置/服務.yaml
services:
App\Security\UserProvider:
arguments:
$em: '@Doctrine\ORM\EntityManagerInterface'
$ldap: '@Symfony\Component\Ldap\Ldap'
$baseDn: "%env(LDAP_BASE_DN)%"
$searchDn: "%env(LDAP_SEARCH_DN)%"
$searchPassword: "%env(LDAP_SEARCH_PASSWORD)%"
$defaultRoles: ["ROLE_USER"]
$uidKey: "uid"
$extraFields: []
App\EventListener\LoginListener:
arguments:
- "@doctrine.orm.entity_manager"
配置/包/security.yml
security:
enable_authenticator_manager: true
password_hashers:
App\Entity\User: 'auto'
providers:
users:
id: App\Security\UserProvider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
lazy: true
provider: users
stateless: false
http_basic_ldap:
service: Symfony\Component\Ldap\Ldap
dn_string: 'uid={username},ou=accounts,dc=example,dc=com'
src/安全/UserProvider.php
<?php
namespace App\Security;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Ldap\Security\LdapUserProvider;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Ldap\Ldap;
use Symfony\Component\Ldap\Security\LdapUser;
class UserProvider extends LdapUserProvider
{
private $em;
public function __construct(EntityManagerInterface $em, Ldap $ldap, string $baseDn, string $searchDn = null, string $searchPassword = null, array $defaultRoles = [], string $uidKey = null, string $filter = null, string $passwordAttribute = null, array $extraFields = [])
{
parent::__construct($ldap, $baseDn, $searchDn, $searchPassword, $defaultRoles, $uidKey, $filter, $passwordAttribute, $extraFields);
$this->em = $em;
}
/**
* Refreshes the user after being reloaded from the session.
*
* @return UserInterface
*/
public function refreshUser(UserInterface $user)
{
if (!$user instanceof User) {
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));
}
$refreshUser = $this->em->getRepository(User::class)->findOneBy(['username' => $user->getUserIdentifier()]);
return $refreshUser;
}
/**
* Tells Symfony to use this provider for this User class.
*/
public function supportsClass(string $class): bool
{
return User::class === $class || is_subclass_of($class, User::class) || LdapUser::class === $class || is_subclass_of($class, LdapUser::class);
}
}
src/EventListener/LoginListener.php
<?php
namespace App\EventListener;
use App\Entity\User;
use Doctrine\ORM\EntityManager;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Ldap\Security\LdapUser;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Http\Event\LoginSuccessEvent;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class LoginListener implements EventSubscriberInterface
{
private $em;
private $tokenStorage;
function __construct(EntityManager $em, TokenStorageInterface $tokenStorage)
{
$this->em = $em;
$this->tokenStorage = $tokenStorage;
}
public static function getSubscribedEvents(): array
{
return [LoginSuccessEvent::class => 'onLoginSuccess'];
}
public function onLoginSuccess(LoginSuccessEvent $loginSuccessEvent)
{
$ldapUser = $loginSuccessEvent->getAuthenticatedToken()->getUser();
if (!($ldapUser instanceof LdapUser)) {
return;
}
$localUser = $this->em->getRepository(User::class)->findOneBy(['username' => $ldapUser->getUserIdentifier()]);
if (!$localUser) {
// No local user found in database -> create new user
$localUser = new User();
$localUser->setUsername($ldapUser->getUserIdentifier());
}
// We don't store user passwords -> generate random token
$rmdBytes = random_bytes(32);
$localUser->setPassword($rmdBytes);
$this->em->persist($localUser);
$this->em->flush();
// Login user
$token = new UsernamePasswordToken($localUser, $rmdBytes, 'main', $localUser->getRoles());
$this->tokenStorage->setToken($token);
}
}
我還按照參考的 stackoverflow 中的建議EquatableInterface在User物體中實施。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/533874.html
標籤:交响乐LDAP
上一篇:目錄不存在時的例外
