我正在与FosUser和FosAuthServer一起在symfony工作。 我有一个前端网站,可以访问 Oauth2 的 API。在前端网站上,如果用户未登录,请将他重定向到 oauth serveur,并在用户登录后,使用 oauth2 令牌将他重定向到字体网站。
它工作得很好,但我需要这个: 如果在数据库中找到用户(我的用户提供者(,longin him 如果在数据库中找不到该用户,我会在LDAP中搜索他并手动登录他。
为此,我使用 AuthenticationFailureHandler 在 LDAP 中查找用户。找到他后,我创建了一个用户实体并调度发明FOSUserEvents::SECURITY_IMPLICIT_LOGIN,但我不知道我可以为谁创建一个令牌并重定向到前面的网站。
安全.yml
security:
encoders:
AppBundleEntityUser: sha512
SymfonyComponentSecurityCoreUserUser: plaintext
providers:
api:
id: fos_user.user_provider.username_email
admin:
memory:
users:
admin: { password: password}
firewalls:
doc:
pattern: ^/api/doc
anonymous: true
oauth_token:
pattern: ^/oauth/v2/token
security: false
oauth_authorize:
pattern: ^/oauth/v2/auth
guard:
authenticators:
- app.security.login_form_authenticator
form_login:
provider: api
csrf_token_generator: security.csrf.token_manager
login_path: fos_user_security_login
check_path: fos_user_security_check
failure_handler: app.authentification_failure_handler
logout:
path: fos_user_security_logout
target: fos_user_security_login
anonymous: true
admin:
pattern: ^/admin
http_basic:
realm: 'Secured Area'
provider: admin
anonymous: false
api:
pattern: ^/api
fos_oauth: true
stateless: true
anonymous: false
access_control:
- { path: ^/oauth/v2/auth, roles: [ IS_AUTHENTICATED_ANONYMOUSLY ] }
- { path: ^/api/doc, roles: [ IS_AUTHENTICATED_ANONYMOUSLY ] }
- { path: ^/admin, roles: [ IS_AUTHENTICATED_FULLY ] }
- { path: ^/, roles: [ ROLE_USER ] }
服务.yml
app.authentification_failure_handler:
public: false
class: AppBundleHandlerAuthenticationFailureHandler
arguments:
- '@utilities.active_directory.ageo'
- '@doctrine.orm.entity_manager'
- '@fos_user.user_manager'
- '@security.token_storage'
- '@debug.event_dispatcher'
- '@router'
- '@http_kernel'
- '@security.http_utils'
AuthentificationFaillureHandler.php
<?php
namespace AppBundleHandler;
use AppBundleEntityAssure;
use AppBundleEntityBrokerStructur;
use DoctrineORMEntityManager;
use DoctrineORMEntityManagerInterface;
use FOSOAuthServerBundleModelAuthCodeManager;
use FOSUserBundleEventFilterUserResponseEvent;
use FOSUserBundleEventGetResponseUserEvent;
use FOSUserBundleEventUserEvent;
use FOSUserBundleFOSUserEvents;
use FOSUserBundleModelUserManager;
use SymfonyComponentHttpFoundationRedirectResponse;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpFoundationSessionSession;
use SymfonyComponentHttpKernelHttpKernelInterface;
use SymfonyComponentRoutingRouterInterface;
use SymfonyComponentSecurityCoreAuthenticationTokenStorageTokenStorage;
use SymfonyComponentSecurityCoreAuthenticationTokenUsernamePasswordToken;
use SymfonyComponentSecurityCoreExceptionAuthenticationException;
use SymfonyComponentSecurityHttpAuthenticationDefaultAuthenticationFailureHandler;
use SymfonyComponentSecurityHttpEventInteractiveLoginEvent;
use SymfonyComponentSecurityHttpHttpUtils;
class AuthenticationFailureHandler extends DefaultAuthenticationFailureHandler
{
// private $cafeteriaEntityManager;
private $router;
/**
* @var AgeoUtilitiesBundleActiveDirectoryAgeo Connection au LDAP Ageo
*/
private $ldap;
/**
* @var $entityManagerSql Manager des entitées de la base mysql
*/
private $entityManagerSql;
/**
* @var UserManager Manager des utilisateurs (FosUserBundle)
*/
private $userManager;
/**
* @var EventDispatcher
*/
private $eventDispatcher;
/**
* @var TokenStorage
*/
private $tokenStorage;
public function __construct(AgeoUtilitiesBundleActiveDirectoryAgeo $ldap, EntityManager $entityManagerSql, UserManager $userManager,
TokenStorage $tokenStorage, SymfonyComponentHttpKernelDebugTraceableEventDispatcher $eventDispatcher,
RouterInterface $router, HttpKernelInterface $httpKernel, HttpUtils $httpUtils)
{
$this->ldap = $ldap;
$this->router = $router;
$this->entityManagerSql = $entityManagerSql;
$this->userManager = $userManager;
$this->tokenStorage = $tokenStorage;
$this->eventDispatcher = $eventDispatcher;
parent::__construct($httpKernel, $httpUtils, array(), null);
}
/**
* Si l'utilisateur n'est pas présent dans la base de données local, on le cherche dans l'Active directory pour le logguer
* On vérifie ensuite s'il existe dans la base de donné local. S'il existe, on le charge et on le met à jour, sinon, on le crée.
* @param Request $request
* @param AuthenticationException $exception
* @return RedirectResponse|SymfonyComponentHttpFoundationResponse
*/
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
$username = trim($request->request->get('_username'));
$password = trim($request->request->get('_password'));
/*
* Manupulation to find the user in LDAP => $userAd
*/
$loaclUser = $this->userManager->createUser();
$loaclUser
->setEnabled(true)
->setUsername($username)
->setPlainPassword($password)
->setEmail($userAd->hasAttribute('mail') ? $userAd->getAttribute('mail')[0] : null )
$this->userManager->updateUser($loaclUser);
$this->eventDispatcher->dispatch(FOSUserEvents::SECURITY_IMPLICIT_LOGIN, new UserEvent($loaclUser, $request));
//$this->eventDispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($loaclUser, $request, $response));
// I need to login my user on authServeur
// I have test this, but it's not working
if ($this->session->has('_security.oauth_authorize.target_path'))
{
parse_str(parse_url($this->session->get('_security.oauth_authorize.target_path'), PHP_URL_QUERY), $target_path);
$url = $this->session->get('_security.oauth_authorize.target_path');
}
$response = new RedirectResponse($url);
return $response;
}
}
有人说我能做login_check的同样过程吗?
我从来没有这样做过,但这似乎是链提供商的用例
security:
providers:
chain_provider:
chain:
providers: [api, admin, ldap_provider]