2 declare(strict_types = 1);
18 use Psr\Http\Message\ResponseInterface;
19 use Psr\Http\Message\ServerRequestInterface;
20 use Psr\Log\LoggerAwareInterface;
21 use Psr\Log\LoggerAwareTrait;
22 use Symfony\Component\HttpFoundation\Cookie;
108 $parsedBody = $request->getParsedBody();
109 $queryParams = $request->getQueryParams();
112 $this->redirectUrl = GeneralUtility::sanitizeLocalUrl($parsedBody[
'redirect_url'] ?? $queryParams[
'redirect_url'] ??
null);
115 $this->loginRefresh = (bool)($parsedBody[
'loginRefresh'] ?? $queryParams[
'loginRefresh'] ??
false);
117 $this->submitValue = $parsedBody[
'commandLI'] ?? $queryParams[
'commandLI'] ??
null;
120 $locales = GeneralUtility::makeInstance(Locales::class);
121 $httpAcceptLanguage = $request->getServerParams()[
'HTTP_ACCEPT_LANGUAGE'];
123 ->getPreferredClientLanguage($httpAcceptLanguage);
129 GeneralUtility::makeInstance(PageRenderer::class)->setLanguage($preferredBrowserLanguage);
135 if ($this->redirectUrl) {
139 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
140 $this->redirectToURL = (string)$uriBuilder->buildUriFromRoute(
'main');
159 public function formAction(ServerRequestInterface $request): ResponseInterface
170 public function refreshAction(ServerRequestInterface $request): ResponseInterface
172 $this->loginRefresh =
true;
183 public function main(): string
185 trigger_error(
'LoginController->main() will be replaced by protected method createLoginLogoutForm() in TYPO3 v10.0. Do not call from other extension.', E_USER_DEPRECATED);
199 $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
200 $pageRenderer->loadRequireJsModule(
'TYPO3/CMS/Backend/Login');
207 $extConf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get(
'backend');
210 if (!empty(
$extConf[
'loginBackgroundImage'])) {
212 if ($backgroundImage ===
'') {
213 $this->logger->warning(
214 'The configured TYPO3 backend login background image "' . htmlspecialchars(
$extConf[
'loginBackgroundImage']) .
215 '" can\'t be resolved. Please check if the file exists and the extension is activated.'
219 .typo3-login-carousel-control.right,
220 .typo3-login-carousel-control.left,
221 .panel-login { border: 0; }
222 .typo3-login { background-image: url("' . $backgroundImage .
'"); }
223 .typo3-login-footnote { background-color: #000000; color: #ffffff; opacity: 0.5; }
228 if (!empty(
$extConf[
'loginFootnote'])) {
229 $this->view->assign(
'loginFootnote', strip_tags(trim(
$extConf[
'loginFootnote'])));
233 if (!empty(
$extConf[
'loginHighlightColor'])) {
235 .btn-login.disabled, .btn-login[disabled], fieldset[disabled] .btn-login,
236 .btn-login.disabled:hover, .btn-login[disabled]:hover, fieldset[disabled] .btn-login:hover,
237 .btn-login.disabled:focus, .btn-login[disabled]:focus, fieldset[disabled] .btn-login:focus,
238 .btn-login.disabled.focus, .btn-login[disabled].focus, fieldset[disabled] .btn-login.focus,
239 .btn-login.disabled:active, .btn-login[disabled]:active, fieldset[disabled] .btn-login:active,
240 .btn-login.disabled.active, .btn-login[disabled].active, fieldset[disabled] .btn-login.active,
241 .btn-login:hover, .btn-login:focus, .btn-login:active,
242 .btn-login:active:hover, .btn-login:active:focus,
243 .btn-login { background-color: ' .
$extConf[
'loginHighlightColor'] .
'; }
244 .panel-login .panel-body { border-color: ' .
$extConf[
'loginHighlightColor'] .
'; }
251 $this->logger->warning(
252 'The configured TYPO3 backend login logo "' . htmlspecialchars(
$extConf[
'loginLogo']) .
253 '" can\'t be resolved. Please check if the file exists and the extension is activated.'
259 if (!empty(
$extConf[
'loginHighlightColor'])) {
260 $logo =
'EXT:backend/Resources/Public/Images/typo3_black.svg';
262 $logo =
'EXT:backend/Resources/Public/Images/typo3_orange.svg';
265 .typo3-login-logo .typo3-login-image { max-width: 150px; height:100%;}
272 $this->view->assignMultiple([
275 'formType' => $formType,
278 'capslock' => $this->
getUriForFileName(
'EXT:backend/Resources/Public/Images/icon_capslock.svg'),
279 'typo3' => $this->
getUriForFileName(
'EXT:backend/Resources/Public/Images/typo3_orange.svg'),
282 'redirectUrl' => $this->redirectUrl,
283 'loginRefresh' => $this->loginRefresh,
285 'referrerCheckEnabled' => GeneralUtility::makeInstance(Features::class)->isFeatureEnabled(
'security.backend.enforceReferrer'),
286 'loginUrl' => (
string)$request->getUri(),
287 'loginProviderIdentifier' => $this->loginProviderIdentifier,
288 'loginProviders' => $this->loginProviders
295 $loginProvider = GeneralUtility::makeInstance($this->loginProviders[$this->loginProviderIdentifier][
'provider']);
296 $loginProvider->render($this->view, $pageRenderer, $this);
299 $content .= $this->view->render();
315 protected function checkRedirect(ServerRequestInterface $request): void
318 if (empty($backendUser->user[
'uid'])) {
328 if ($this->submitValue ===
'setCookie') {
334 throw new \RuntimeException(
'Login-error: Yeah, that\'s a classic. No cookies, no TYPO3. ' .
335 'Please accept cookies from TYPO3 - otherwise you\'ll not be able to use the system.', 1294586846);
338 $this->redirectToURL =
'index.php?commandLI=setCookie';
340 $redirectToUrl = (string)($backendUser->getTSConfig()[
'auth.'][
'BE.'][
'redirectToURL'] ??
'');
341 if (empty($redirectToUrl)) {
343 $parsedBody = $request->getParsedBody();
344 $queryParams = $request->getQueryParams();
345 $interface = $parsedBody[
'interface'] ?? $queryParams[
'interface'] ??
'';
346 switch ($interface) {
348 $this->redirectToURL =
'../';
352 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
353 $this->redirectToURL = (string)$uriBuilder->buildUriFromRoute(
'main');
357 $this->redirectToURL = $redirectToUrl;
361 $backendUser->uc[
'interfaceSetup'] = $interface;
362 $backendUser->writeUC();
365 if (!$formProtection instanceof BackendFormProtection) {
366 throw new \RuntimeException(
'The Form Protection retrieved does not match the expected one.', 1432080411);
368 if ($this->loginRefresh) {
369 $formProtection->setSessionTokenFromRegistry();
370 $formProtection->persistSessionToken();
372 if (window.opener && window.opener.TYPO3 && window.opener.TYPO3.LoginRefresh) {
373 window.opener.TYPO3.LoginRefresh.startTask();
378 $formProtection->storeSessionTokenInRegistry();
390 trigger_error(
'LoginController->makeInterfaceSelectorBox() will be replaced by protected method makeInterfaceSelector() in TYPO3 v10.0. Do not call from other extension.', E_USER_DEPRECATED);
402 $parts = GeneralUtility::trimExplode(
',',
$GLOBALS[
'TYPO3_CONF_VARS'][
'BE'][
'interfaces']);
403 if (count($parts) > 1) {
405 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
409 'jumpScript' => (string)$uriBuilder->buildUriFromRoute(
'main'),
410 'interface' =>
'backend'
414 'jumpScript' =>
'../',
415 'interface' =>
'frontend'
419 $this->view->assign(
'showInterfaceSelector',
true);
420 $this->view->assign(
'interfaces', $interfaces);
421 } elseif (!$this->redirectUrl) {
423 $this->view->assign(
'showInterfaceSelector',
false);
424 $this->view->assign(
'interface', $parts[0]);
437 $systemNewsTable =
'sys_news';
438 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
439 ->getQueryBuilderForTable($systemNewsTable);
441 $systemNewsRecords = $queryBuilder
442 ->select(
'title',
'content',
'crdate')
443 ->from($systemNewsTable)
444 ->orderBy(
'crdate',
'DESC')
447 foreach ($systemNewsRecords as $systemNewsRecord) {
449 'date' => date(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'ddmmyy'], (
int)$systemNewsRecord[
'crdate']),
450 'header' => $systemNewsRecord[
'title'],
451 'content' => $systemNewsRecord[
'content']
469 if (preg_match(
'/^(https?:)?\/\//', $filename)) {
472 $absoluteFilename = GeneralUtility::getFileAbsFileName(ltrim($filename,
'/'));
474 if ($absoluteFilename !==
'' && @is_file($absoluteFilename)) {
488 $parsedBody = $request->getParsedBody();
489 $queryParams = $request->getQueryParams();
490 $username = $parsedBody[
'username'] ?? $queryParams[
'username'] ??
null;
491 return !empty($username) || !empty($this->submitValue);
502 $view = GeneralUtility::makeInstance(StandaloneView::class);
526 $providers =
$GLOBALS[
'TYPO3_CONF_VARS'][
'EXTCONF'][
'backend'][
'loginProviders'] ?? [];
527 if (empty($providers) || !is_array($providers)) {
528 throw new \RuntimeException(
'No login providers are registered in $GLOBALS[\'TYPO3_CONF_VARS\'][\'EXTCONF\'][\'backend\'][\'loginProviders\'].', 1433417281);
530 foreach ($providers as $identifier => $configuration) {
531 if (empty($configuration) || !is_array($configuration)) {
532 throw new \RuntimeException(
'Missing configuration for login provider "' . $identifier .
'".', 1433416043);
534 if (!is_string($configuration[
'provider']) || empty($configuration[
'provider']) || !class_exists($configuration[
'provider']) || !is_subclass_of($configuration[
'provider'], LoginProviderInterface::class)) {
535 throw new \RuntimeException(
'The login provider "' . $identifier .
'" defines an invalid provider. Ensure the class exists and implements the "' . LoginProviderInterface::class .
'".', 1460977275);
537 if (empty($configuration[
'label'])) {
538 throw new \RuntimeException(
'Missing label definition for login provider "' . $identifier .
'".', 1433416044);
540 if (empty($configuration[
'icon-class'])) {
541 throw new \RuntimeException(
'Missing icon definition for login provider "' . $identifier .
'".', 1433416045);
543 if (!isset($configuration[
'sorting'])) {
544 throw new \RuntimeException(
'Missing sorting definition for login provider "' . $identifier .
'".', 1433416046);
548 uasort($providers,
function ($a, $b) {
549 return $b[
'sorting'] - $a[
'sorting'];
551 $this->loginProviders = $providers;
563 $parsedBody = $request->getParsedBody();
564 $queryParams = $request->getQueryParams();
565 $loginProvider = $parsedBody[
'loginProvider'] ?? $queryParams[
'loginProvider'] ??
'';
566 if ((empty($loginProvider) || !isset($this->loginProviders[$loginProvider])) && !empty($_COOKIE[
'be_lastLoginProvider'])) {
567 $loginProvider = $_COOKIE[
'be_lastLoginProvider'];
569 if (empty($loginProvider) || !isset($this->loginProviders[$loginProvider])) {
570 reset($this->loginProviders);
571 $loginProvider = key($this->loginProviders);
575 $normalizedParams = $request->getAttribute(
'normalizedParams');
576 $isHttps = $normalizedParams->isHttps();
577 $cookieSecure = (bool)
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'cookieSecure'] && $isHttps;
578 $cookie =
new Cookie(
579 'be_lastLoginProvider',
580 (
string)$loginProvider,
582 $normalizedParams->getSitePath() . TYPO3_mainDir,
587 Cookie::SAMESITE_STRICT
589 header(
'Set-Cookie: ' . $cookie->__toString(),
false);
591 return (
string)$loginProvider;