Я работаю над интранет-сайтом, который будет использовать Symfony 2.6.
Мне удалось создать собственного провайдера безопасности / прослушивателя и т. Д., Чтобы обеспечить аутентификацию NTLM (на основе входа в Windows).
Мне также удалось совместить это с получением ролей из базы данных.
Сейчас я работаю над способностью switch_user и считаю, что моя аутентификация противоречит процессу олицетворения, как показано в журналах рядом.
Я USER1 (из NTLM) и хочу выдать себя за USER2, запись в журнале с ** была повторно объяснена для ясности
[2015-07-18 22:17:47] request.INFO: Matched route "homepage_conception" (parameters: "mode": "conception", "_controller": "AppBundle\Controller\MainController::indexAction", "_route": "homepage_conception") [] []
[2015-07-18 22:17:48] security.DEBUG: Read SecurityContext from the session [] []
[2015-07-18 22:17:48] security.DEBUG: Reloading user from user provider. [] []
[2015-07-18 22:17:48] doctrine.DEBUG: ** SELECT query for USER1 (based on id) ** []
[2015-07-18 22:17:48] security.DEBUG: Username "USER1" was reloaded from user provider. [] []
[2015-07-18 22:17:48] app.DEBUG: NTLM Authentication - Handshake Step 1 [] []
[2015-07-18 22:17:48] app.DEBUG: NTLM Authentication - Requesting from client - WWW-Authenticate: NTLM [] []
Во время аутентификации NTLM запрос повторно отправляется 3 раза (здесь 2-й раунд)
[2015-07-18 22:17:48] request.INFO: Matched route "homepage_conception" (parameters: "mode": "conception", "_controller": "AppBundle\Controller\MainController::indexAction", "_route": "homepage_conception") [] []
[2015-07-18 22:17:49] security.DEBUG: Read SecurityContext from the session [] []
[2015-07-18 22:17:49] security.DEBUG: Reloading user from user provider. [] []
[2015-07-18 22:17:49] doctrine.DEBUG: ** SELECT query for USER1 (based on id) ** []
[2015-07-18 22:17:49] security.DEBUG: Username "USER1" was reloaded from user provider. [] []
[2015-07-18 22:17:49] app.DEBUG: NTLM Authentication - Handshake Step 2 [] []
[2015-07-18 22:17:49] app.DEBUG: NTLM Authentication - Requesting from client - WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAACgAAAABggAAAAICAgAAAAAAAAAAAAAAAA== [] []
NTLM третий раунд
[2015-07-18 22:17:49] request.INFO: Matched route "homepage_conception" (parameters: "mode": "conception", "_controller": "AppBundle\Controller\MainController::indexAction", "_route": "homepage_conception") [] []
[2015-07-18 22:17:49] security.DEBUG: Read SecurityContext from the session [] []
[2015-07-18 22:17:49] security.DEBUG: Reloading user from user provider. [] []
[2015-07-18 22:17:49] doctrine.DEBUG: ** SELECT query for USER1 (based on id) ** []
[2015-07-18 22:17:49] security.DEBUG: Username "USER1" was reloaded from user provider. [] []
[2015-07-18 22:17:49] app.DEBUG: NTLM Authentication - Handshake Step 3 [] []
[2015-07-18 22:17:49] app.DEBUG: NTLM Authentication - Got user info, creating token with username USER1 [] []
[2015-07-18 22:17:49] doctrine.DEBUG: ** SELECT query to get full user object (based on username) ** ["USER1"] []
[2015-07-18 22:17:49] doctrine.DEBUG: ** SELECT query to know role for USER1 id from mapping table (based on id) ** ** []
[2015-07-18 22:17:50] doctrine.DEBUG: ** SELECT query to have role object (based on role id) ** [96] []
[2015-07-18 22:17:50] doctrine.DEBUG: ** SELECT query to have role object (based on role id) ** [97] []
Я в! Попытка сменить пользователя …
[2015-07-18 22:17:50] security.INFO: Attempt to switch to user "USER2" [] []
[2015-07-18 22:17:50] doctrine.DEBUG: ** SELECT query to get full user object (based on username) ** ["USER2"] []
[2015-07-18 22:17:50] doctrine.DEBUG: ** SELECT query to know role for USER2 id from mapping table (based on id) ** [5] []
[2015-07-18 22:17:50] ... various event "kernel..." I can provide them if needed
[2015-07-18 22:17:50] event.DEBUG: Listener "Symfony\Component\Security\Http\Firewall::onKernelRequest" stopped propagation of the event "kernel.request". [] []
[2015-07-18 22:17:50] event.DEBUG: Listener "Symfony\Bundle\AsseticBundle\EventListener\RequestListener::onKernelRequest" was not called for event "kernel.request". [] []
[2015-07-18 22:17:50] security.DEBUG: Write SecurityContext in the session [] []
[2015-07-18 22:17:50] ... various event "kernel..." I can provide them if needed
Снова (!?) В рукопожатии NTLM … (1/3)
[2015-07-18 22:17:50] request.INFO: Matched route "homepage_conception" (parameters: "mode": "conception", "_controller": "AppBundle\Controller\MainController::indexAction", "_route": "homepage_conception") [] []
[2015-07-18 22:17:50] security.DEBUG: Read SecurityContext from the session [] []
[2015-07-18 22:17:50] security.DEBUG: Reloading user from user provider. [] []
[2015-07-18 22:17:50] doctrine.DEBUG: ** SELECT query for USER2 (based on id) ** []
[2015-07-18 22:17:50] security.DEBUG: Username "USER2" was reloaded from user provider. [] []
[2015-07-18 22:17:51] app.DEBUG: NTLM Authentication - Handshake Step 1 [] []
[2015-07-18 22:17:51] app.DEBUG: NTLM Authentication - Requesting from client - WWW-Authenticate: NTLM [] []
NTLM 2/3
[2015-07-18 22:17:51] request.INFO: Matched route "homepage_conception" (parameters: "mode": "conception", "_controller": "AppBundle\Controller\MainController::indexAction", "_route": "homepage_conception") [] []
[2015-07-18 22:17:51] security.DEBUG: Read SecurityContext from the session [] []
[2015-07-18 22:17:51] security.DEBUG: Reloading user from user provider. [] []
[2015-07-18 22:17:51] doctrine.DEBUG: ** SELECT query for USER2 (based on id) ** []
[2015-07-18 22:17:51] security.DEBUG: Username "USER2" was reloaded from user provider. [] []
[2015-07-18 22:17:51] app.DEBUG: NTLM Authentication - Handshake Step 2 [] []
[2015-07-18 22:17:51] app.DEBUG: NTLM Authentication - Requesting from client - WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAACgAAAABggAAAAICAgAAAAAAAAAAAAAAAA== [] []
NTLM 3/3
[2015-07-18 22:17:52] request.INFO: Matched route "homepage_conception" (parameters: "mode": "conception", "_controller": "AppBundle\Controller\MainController::indexAction", "_route": "homepage_conception") [] []
[2015-07-18 22:17:52] security.DEBUG: Read SecurityContext from the session [] []
[2015-07-18 22:17:52] security.DEBUG: Reloading user from user provider. [] []
[2015-07-18 22:17:52] doctrine.DEBUG: ** SELECT query for USER2 (based on id) ** []
[2015-07-18 22:17:52] security.DEBUG: Username "USER2" was reloaded from user provider. [] []
[2015-07-18 22:17:52] app.DEBUG: NTLM Authentication - Handshake Step 3 [] []
[2015-07-18 22:17:52] app.DEBUG: NTLM Authentication - Got user info, creating token with username USER1 [] []
[2015-07-18 22:17:52] doctrine.DEBUG: ** SELECT query to get full user object (based on username) ** ["USER1"] []
[2015-07-18 22:17:52] doctrine.DEBUG: ** SELECT query to know role for USER1 id from mapping table (based on id) ** []
[2015-07-18 22:17:52] doctrine.DEBUG: ** SELECT query to have role object (based on role id) ** [96] []
[2015-07-18 22:17:52] doctrine.DEBUG: ** SELECT query to have role object (based on role id) ** [97] []
[2015-07-18 22:17:52] ... various event "kernel..." I can provide them if needed
Есть ли у кого-нибудь подсказки о том, как заставить все эти вещи работать вместе?
Вот мой код NTLMListener
namespace AppBundle\Security\Firewall;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Http\Firewall\ListenerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use AppBundle\Security\Authentication\Token\NtlmUserToken;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
class NtlmListener implements ListenerInterface
{
protected $securityContext;
protected $authenticationManager;
protected $logger;
public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, LoggerInterface $logger)
{
$this->securityContext = $securityContext;
$this->authenticationManager = $authenticationManager;
$this->logger = $logger;
}
private function unAuthorized($msg=null) {
$ntlm = 'WWW-Authenticate: NTLM';
if ($msg) {
$ntlm .= ' '.$msg;
}
header('HTTP1.0 401 Unauthorized');
header($ntlm);
$this->logger->debug("NTLM Authentication - Requesting from client - ".$ntlm);
return 1; // NTLM_AUTH_FAILED
}
private function getInfosFromNTLM() {
if (!empty($_SERVER['HTTP_VIA'])) {
return 2; // NTLM_PROXY
}
$header = apache_request_headers();
$auth = isset($header['Authorization']) ? $header['Authorization'] : null;
if (is_null($auth)) {
$this->logger->debug("NTLM Authentication - Handshake Step 1");
return $this->unAuthorized();
}
if ($auth && (substr($auth,0,4) == 'NTLM')) {
$c64 = base64_decode(substr($auth,5));
$state = ord($c64{8});
switch ($state) {
case 1:
$this->logger->debug("NTLM Authentication - Handshake Step 2");
$chrs = array(0,2,0,0,0,0,0,0,0,40,0,0,0,1,130,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0);
$ret = "NTLMSSP";
foreach ($chrs as $chr) {
$ret .= chr($chr);
}
return $this->unAuthorized(trim(base64_encode($ret)));
case 3:
$this->logger->debug("NTLM Authentication - Handshake Step 3");
$l = ord($c64{31}) * 256 + ord($c64{30});
$o = ord($c64{33}) * 256 + ord($c64{32});
$domain = str_replace("\0","",substr($c64,$o,$l));
$l = ord($c64{39}) * 256 + ord($c64{38});
$o = ord($c64{41}) * 256 + ord($c64{40});
$user = str_replace("\0","",substr($c64,$o,$l));
return array('domain'=>$domain,'user'=>$user);
}
}
return 3;
}
public function handle(GetResponseEvent $event)
{
header('WWW-Authenticate: Negociate');
$infos = $this->getInfosFromNTLM();
switch ($infos) {
case 3:
case 2:
// NTLM not available ... give up
return;
case 1:
//header sent, client will re-send request (if NTLM aware)
exit;
default:
}
$this->logger->debug("NTLM Authentication - Got user info, creating token with username ".$infos["user"]);
$token = new NtlmUserToken();
$token->setUser($infos['user']);
try {
$authToken = $this->authenticationManager->authenticate($token);
$this->securityContext->setToken($authToken);
} catch (AuthenticationException $failed) {
// Deny authentication with a '403 Forbidden' HTTP response
$response = new Response($failed);
$response->setStatusCode(403);
$event->setResponse($response);
}
}
}
Задача ещё не решена.
Других решений пока нет …