我正在与FosUser和FosAuthServer合作。 我有一个前端网站,可以通过Oauth2访问API。在前端网站上,如果用户未登录,则将其重定向到oauth服务器,然后在用户登录后,使用oauth2令牌将其重定向到字体网站。
效果很好,但是我需要这个: 如果在数据库中找到了用户(我的用户提供者),请 如果在数据库中找不到该用户,我将在LDAP中对其进行搜索,然后手动登录。
为此,我使用AuthenticationFailureHandler在LDAP中查找用户。找到他之后,我创建了一个用户实体并调度了FOSUserEvents :: SECURITY_IMPLICIT_LOGIN,但是我不知道谁可以创建令牌并重定向到前端网站。
security.yml
security:
encoders:
AppBundle\Entity\User: sha512
Symfony\Component\Security\Core\User\User: 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 ] }
Service.yml
app.authentification_failure_handler:
public: false
class: AppBundle\Handler\AuthenticationFailureHandler
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 AppBundle\Handler;
use AppBundle\Entity\Assure;
use AppBundle\Entity\BrokerStructur;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityManagerInterface;
use FOS\OAuthServerBundle\Model\AuthCodeManager;
use FOS\UserBundle\Event\FilterUserResponseEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\Event\UserEvent;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Model\UserManager;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationFailureHandler;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\HttpUtils;
class AuthenticationFailureHandler extends DefaultAuthenticationFailureHandler
{
// private $cafeteriaEntityManager;
private $router;
/**
* @var \Ageo\UtilitiesBundle\ActiveDirectory\Ageo 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(\Ageo\UtilitiesBundle\ActiveDirectory\Ageo $ldap, EntityManager $entityManagerSql, UserManager $userManager,
TokenStorage $tokenStorage, \Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher $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|\Symfony\Component\HttpFoundation\Response
*/
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做同样的过程吗?
答案 0 :(得分:1)
我从没做过,但这似乎是chain provider
的用例security:
providers:
chain_provider:
chain:
providers: [api, admin, ldap_provider]