TYPO3 CMS  TYPO3_6-2
FrontendUserAuthentication.php
Go to the documentation of this file.
1 <?php
3 
17 
25 
33  public $formfield_permanent = 'permalogin';
34 
39  protected $sessionDataLifetime = 86400;
40 
45  public $usergroup_column = 'usergroup';
46 
51  public $usergroup_table = 'fe_groups';
52 
57  public $groupData = array(
58  'title' => array(),
59  'uid' => array(),
60  'pid' => array()
61  );
62 
68  public $TSdataArray = array();
69 
74  public $userTS = array();
75 
80  public $userTSUpdated = FALSE;
81 
93  public $sesData = array();
94 
99  public $sesData_change = FALSE;
100 
105  public $userData_change = FALSE;
106 
111 
115  protected $sessionDataTimestamp = NULL;
116 
120  protected $loginHidden = FALSE;
121 
125  public function __construct() {
126  parent::__construct();
127 
128  // Disable cookie by default, will be activated if saveSessionData() is called,
129  // a user is logging-in or an existing session is found
130  $this->dontSetCookie = TRUE;
131 
132  $this->session_table = 'fe_sessions';
133  $this->name = self::getCookieName();
134  $this->get_name = 'ftu';
135  $this->loginType = 'FE';
136  $this->user_table = 'fe_users';
137  $this->username_column = 'username';
138  $this->userident_column = 'password';
139  $this->userid_column = 'uid';
140  $this->lastLogin_column = 'lastlogin';
141  $this->enablecolumns = array(
142  'deleted' => 'deleted',
143  'disabled' => 'disable',
144  'starttime' => 'starttime',
145  'endtime' => 'endtime'
146  );
147  $this->formfield_uname = 'user';
148  $this->formfield_uident = 'pass';
149  $this->formfield_chalvalue = 'challenge';
150  $this->formfield_status = 'logintype';
151  $this->auth_timeout_field = 6000;
152  $this->sendNoCacheHeaders = FALSE;
153  $this->getFallBack = TRUE;
154  $this->getMethodEnabled = TRUE;
155  }
156 
162  static public function getCookieName() {
163  $configuredCookieName = trim($GLOBALS['TYPO3_CONF_VARS']['FE']['cookieName']);
164  if (empty($configuredCookieName)) {
165  $configuredCookieName = 'fe_typo_user';
166  }
167  return $configuredCookieName;
168  }
169 
177  public function start() {
178  if ((int)$this->auth_timeout_field > 0 && (int)$this->auth_timeout_field < $this->lifetime) {
179  // If server session timeout is non-zero but less than client session timeout: Copy this value instead.
180  $this->auth_timeout_field = $this->lifetime;
181  }
182  $this->sessionDataLifetime = (int)$GLOBALS['TYPO3_CONF_VARS']['FE']['sessionDataLifetime'];
183  if ($this->sessionDataLifetime <= 0) {
184  $this->sessionDataLifetime = 86400;
185  }
186  parent::start();
187  }
188 
196  public function getNewSessionRecord($tempuser) {
197  $insertFields = parent::getNewSessionRecord($tempuser);
198  $insertFields['ses_permanent'] = $this->is_permanent;
199  return $insertFields;
200  }
201 
209  public function isSetSessionCookie() {
210  return ($this->newSessionID || $this->forceSetCookie)
211  && ($this->lifetime == 0 || !isset($this->user['ses_permanent']) || !$this->user['ses_permanent']);
212  }
213 
221  public function isRefreshTimeBasedCookie() {
222  return $this->lifetime > 0 && isset($this->user['ses_permanent']) && $this->user['ses_permanent'];
223  }
224 
232  public function getLoginFormData() {
233  $loginData = parent::getLoginFormData();
234  if ($GLOBALS['TYPO3_CONF_VARS']['FE']['permalogin'] == 0 || $GLOBALS['TYPO3_CONF_VARS']['FE']['permalogin'] == 1) {
235  if ($this->getMethodEnabled) {
236  $isPermanent = GeneralUtility::_GP($this->formfield_permanent);
237  } else {
238  $isPermanent = GeneralUtility::_POST($this->formfield_permanent);
239  }
240  if (strlen($isPermanent) != 1) {
241  $isPermanent = $GLOBALS['TYPO3_CONF_VARS']['FE']['permalogin'];
242  } elseif (!$isPermanent) {
243  // To make sure the user gets a session cookie and doesn't keep a possibly existing time based cookie,
244  // we need to force seeting the session cookie here
245  $this->forceSetCookie = TRUE;
246  }
247  $isPermanent = $isPermanent ? 1 : 0;
248  } elseif ($GLOBALS['TYPO3_CONF_VARS']['FE']['permalogin'] == 2) {
249  $isPermanent = 1;
250  } else {
251  $isPermanent = 0;
252  }
253  $loginData['permanent'] = $isPermanent;
254  $this->is_permanent = $isPermanent;
255  return $loginData;
256  }
257 
266  public function createUserSession($tempuser) {
267  // At this point we do not know if we need to set a session or a "permanant" cookie
268  // So we force the cookie to be set after authentication took place, which will
269  // then call setSessionCookie(), which will set a cookie with correct settings.
270  $this->dontSetCookie = FALSE;
271  return parent::createUserSession($tempuser);
272  }
273 
282  public function fetchGroupData() {
283  $this->TSdataArray = array();
284  $this->userTS = array();
285  $this->userTSUpdated = FALSE;
286  $this->groupData = array(
287  'title' => array(),
288  'uid' => array(),
289  'pid' => array()
290  );
291  // Setting default configuration:
292  $this->TSdataArray[] = $GLOBALS['TYPO3_CONF_VARS']['FE']['defaultUserTSconfig'];
293  // Get the info data for auth services
294  $authInfo = $this->getAuthInfoArray();
295  if ($this->writeDevLog) {
296  if (is_array($this->user)) {
297  GeneralUtility::devLog('Get usergroups for user: ' . GeneralUtility::arrayToLogString($this->user, array($this->userid_column, $this->username_column)), 'TYPO3\\CMS\\Frontend\\Authentication\\FrontendUserAuthentication');
298  } else {
299  GeneralUtility::devLog('Get usergroups for "anonymous" user', 'TYPO3\\CMS\\Frontend\\Authentication\\FrontendUserAuthentication');
300  }
301  }
302  $groupDataArr = array();
303  // Use 'auth' service to find the groups for the user
304  $serviceChain = '';
305  $subType = 'getGroups' . $this->loginType;
306  while (is_object($serviceObj = GeneralUtility::makeInstanceService('auth', $subType, $serviceChain))) {
307  $serviceChain .= ',' . $serviceObj->getServiceKey();
308  $serviceObj->initAuth($subType, array(), $authInfo, $this);
309  $groupData = $serviceObj->getGroups($this->user, $groupDataArr);
310  if (is_array($groupData) && count($groupData)) {
311  // Keys in $groupData should be unique ids of the groups (like "uid") so this function will override groups.
312  $groupDataArr = GeneralUtility::array_merge($groupDataArr, $groupData);
313  }
314  unset($serviceObj);
315  }
316  if ($this->writeDevLog && $serviceChain) {
317  GeneralUtility::devLog($subType . ' auth services called: ' . $serviceChain, 'TYPO3\\CMS\\Frontend\\Authentication\\FrontendUserAuthentication');
318  }
319  if ($this->writeDevLog && !count($groupDataArr)) {
320  GeneralUtility::devLog('No usergroups found by services', 'TYPO3\\CMS\\Frontend\\Authentication\\FrontendUserAuthentication');
321  }
322  if ($this->writeDevLog && count($groupDataArr)) {
323  GeneralUtility::devLog(count($groupDataArr) . ' usergroup records found by services', 'TYPO3\\CMS\\Frontend\\Authentication\\FrontendUserAuthentication');
324  }
325  // Use 'auth' service to check the usergroups if they are really valid
326  foreach ($groupDataArr as $groupData) {
327  // By default a group is valid
328  $validGroup = TRUE;
329  $serviceChain = '';
330  $subType = 'authGroups' . $this->loginType;
331  while (is_object($serviceObj = GeneralUtility::makeInstanceService('auth', $subType, $serviceChain))) {
332  $serviceChain .= ',' . $serviceObj->getServiceKey();
333  $serviceObj->initAuth($subType, array(), $authInfo, $this);
334  if (!$serviceObj->authGroup($this->user, $groupData)) {
335  $validGroup = FALSE;
336  if ($this->writeDevLog) {
337  GeneralUtility::devLog($subType . ' auth service did not auth group: ' . GeneralUtility::arrayToLogString($groupData, 'uid,title'), 'TYPO3\\CMS\\Frontend\\Authentication\\FrontendUserAuthentication', 2);
338  }
339  break;
340  }
341  unset($serviceObj);
342  }
343  unset($serviceObj);
344  if ($validGroup && (string)$groupData['uid'] !== '') {
345  $this->groupData['title'][$groupData['uid']] = $groupData['title'];
346  $this->groupData['uid'][$groupData['uid']] = $groupData['uid'];
347  $this->groupData['pid'][$groupData['uid']] = $groupData['pid'];
348  $this->groupData['TSconfig'][$groupData['uid']] = $groupData['TSconfig'];
349  }
350  }
351  if (count($this->groupData) && count($this->groupData['TSconfig'])) {
352  // TSconfig: collect it in the order it was collected
353  foreach ($this->groupData['TSconfig'] as $TSdata) {
354  $this->TSdataArray[] = $TSdata;
355  }
356  $this->TSdataArray[] = $this->user['TSconfig'];
357  // Sort information
358  ksort($this->groupData['title']);
359  ksort($this->groupData['uid']);
360  ksort($this->groupData['pid']);
361  }
362  return count($this->groupData['uid']) ?: 0;
363  }
364 
372  public function getUserTSconf() {
373  if (!$this->userTSUpdated) {
374  // Parsing the user TS (or getting from cache)
376  $userTS = implode(LF . '[GLOBAL]' . LF, $this->TSdataArray);
377  $parseObj = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\TypoScript\\Parser\\TypoScriptParser');
378  $parseObj->parse($userTS);
379  $this->userTS = $parseObj->setup;
380  $this->userTSUpdated = TRUE;
381  }
382  return $this->userTS;
383  }
384 
385  /*****************************************
386  *
387  * Session data management functions
388  *
389  ****************************************/
400  public function fetchSessionData() {
401  // Gets SesData if any AND if not already selected by session fixation check in ->isExistingSessionRecord()
402  if ($this->id && !count($this->sesData)) {
403  $statement = $this->db->prepare_SELECTquery('*', 'fe_session_data', 'hash = :hash');
404  $statement->execute(array(':hash' => $this->id));
405  if (($sesDataRow = $statement->fetch()) !== FALSE) {
406  $this->sesData = unserialize($sesDataRow['content']);
407  $this->sessionDataTimestamp = $sesDataRow['tstamp'];
408  }
409  $statement->free();
410  }
411  }
412 
423  public function storeSessionData() {
424  // Saves UC and SesData if changed.
425  if ($this->userData_change) {
426  $this->writeUC('');
427  }
428  if ($this->sesData_change && $this->id) {
429  if (empty($this->sesData)) {
430  // Remove session-data
431  $this->removeSessionData();
432  // Remove cookie if not logged in as the session data is removed as well
433  if (empty($this->user['uid']) && !$this->loginHidden && $this->isCookieSet()) {
434  $this->removeCookie($this->name);
435  }
436  } elseif ($this->sessionDataTimestamp === NULL) {
437  // Write new session-data
438  $insertFields = array(
439  'hash' => $this->id,
440  'content' => serialize($this->sesData),
441  'tstamp' => $GLOBALS['EXEC_TIME']
442  );
443  $this->sessionDataTimestamp = $GLOBALS['EXEC_TIME'];
444  $this->db->exec_INSERTquery('fe_session_data', $insertFields);
445  // Now set the cookie (= fix the session)
446  $this->setSessionCookie();
447  } else {
448  // Update session data
449  $updateFields = array(
450  'content' => serialize($this->sesData),
451  'tstamp' => $GLOBALS['EXEC_TIME']
452  );
453  $this->sessionDataTimestamp = $GLOBALS['EXEC_TIME'];
454  $this->db->exec_UPDATEquery('fe_session_data', 'hash=' . $this->db->fullQuoteStr($this->id, 'fe_session_data'), $updateFields);
455  }
456  }
457  }
458 
464  public function removeSessionData() {
465  $this->sessionDataTimestamp = NULL;
466  $this->db->exec_DELETEquery('fe_session_data', 'hash=' . $this->db->fullQuoteStr($this->id, 'fe_session_data'));
467  }
468 
477  public function logoff() {
478  parent::logoff();
479  // Remove the cookie on log-off, but only if we do not have an anonymous session
480  if (!$this->isExistingSessionRecord($this->id) && $this->isCookieSet()) {
481  $this->removeCookie($this->name);
482  }
483  }
484 
489  protected function regenerateSessionId() {
490  $oldSessionId = $this->id;
491  parent::regenerateSessionId();
492  // Update session data with new ID
493  $this->db->exec_UPDATEquery(
494  'fe_session_data',
495  'hash=' . $this->db->fullQuoteStr($oldSessionId, 'fe_session_data'),
496  array('hash' => $this->id)
497  );
498 
499  $this->dontSetCookie = FALSE;
500  }
501 
508  public function gc() {
509  $timeoutTimeStamp = (int)($GLOBALS['EXEC_TIME'] - $this->sessionDataLifetime);
510  $this->db->exec_DELETEquery('fe_session_data', 'tstamp < ' . $timeoutTimeStamp);
511  parent::gc();
512  }
513 
524  public function getKey($type, $key) {
525  if (!$key) {
526  return NULL;
527  }
528  $value = NULL;
529  switch ($type) {
530  case 'user':
531  $value = $this->uc[$key];
532  break;
533  case 'ses':
534  $value = $this->sesData[$key];
535  break;
536  }
537  return $value;
538  }
539 
553  public function setKey($type, $key, $data) {
554  if (!$key) {
555  return;
556  }
557  switch ($type) {
558  case 'user':
559  if ($this->user['uid']) {
560  if ($data === NULL) {
561  unset($this->uc[$key]);
562  } else {
563  $this->uc[$key] = $data;
564  }
565  $this->userData_change = TRUE;
566  }
567  break;
568  case 'ses':
569  if ($data === NULL) {
570  unset($this->sesData[$key]);
571  } else {
572  $this->sesData[$key] = $data;
573  }
574  $this->sesData_change = TRUE;
575  break;
576  }
577  }
578 
586  public function getSessionData($key) {
587  return $this->getKey('ses', $key);
588  }
589 
597  public function setAndSaveSessionData($key, $data) {
598  $this->setKey('ses', $key, $data);
599  $this->storeSessionData();
600  }
601 
612  public function record_registration($recs, $maxSizeOfSessionData = 0) {
613  // Storing value ONLY if there is a confirmed cookie set,
614  // otherwise a shellscript could easily be spamming the fe_sessions table
615  // with bogus content and thus bloat the database
616  if (!$maxSizeOfSessionData || $this->isCookieSet()) {
617  if ($recs['clear_all']) {
618  $this->setKey('ses', 'recs', array());
619  }
620  $change = 0;
621  $recs_array = $this->getKey('ses', 'recs');
622  foreach ($recs as $table => $data) {
623  if (is_array($data)) {
624  foreach ($data as $rec_id => $value) {
625  if ($value != $recs_array[$table][$rec_id]) {
626  $recs_array[$table][$rec_id] = $value;
627  $change = 1;
628  }
629  }
630  }
631  }
632  if ($change && (!$maxSizeOfSessionData || strlen(serialize($recs_array)) < $maxSizeOfSessionData)) {
633  $this->setKey('ses', 'recs', $recs_array);
634  }
635  }
636  }
637 
648  public function isExistingSessionRecord($id) {
649  // Perform check in parent function
650  $count = parent::isExistingSessionRecord($id);
651  // Check if there are any fe_session_data records for the session ID the client claims to have
652  if ($count == FALSE) {
653  $statement = $this->db->prepare_SELECTquery('content,tstamp', 'fe_session_data', 'hash = :hash');
654  $res = $statement->execute(array(':hash' => $id));
655  if ($res !== FALSE) {
656  if ($sesDataRow = $statement->fetch()) {
657  $count = TRUE;
658  $this->sesData = unserialize($sesDataRow['content']);
659  $this->sessionDataTimestamp = $sesDataRow['tstamp'];
660  }
661  $statement->free();
662  }
663  }
664  return $count;
665  }
666 
675  public function hideActiveLogin() {
676  $this->user = NULL;
677  $this->loginHidden = TRUE;
678  }
679 
680 }
$configuredCookieName
Definition: index_ts.php:39
static devLog($msg, $extKey, $severity=0, $dataVar=FALSE)
static arrayToLogString(array $arr, $valueList=array(), $valueLength=20)
static makeInstanceService($serviceType, $serviceSubType='', $excludeServiceKeys=array())
static array_merge(array $arr1, array $arr2)
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]