php

’tag’

Remember Me для Админ зоны в Joomla 3.2.3

Апрель 5, 2014

Вот это самое интересное и с бубном пришлось плясать очень долго. Но цель достигнута - можно хоть выключить браузер и компьютер, при следующем включении вы будете авторизованы в Администраторе, как если бы вы были на пользовательской части сайта.

Сразу отмечу, что ни один плагин в Интернете не позволяет достигнуть аналогичного результата. Причем в моем случае почему-то даже стандартный KeepAlive не работал, сессия слетала и я переключался на форму логина каждые 15 минут (время жизни сессии по настройкам конфига). Сейчас даже если и сессия слетела, она восстановится. ОК, к делу.

Все правки в коде ищите по комментарию "// cay127".

Файл plugins/authentication/cookie/cookie.php

Правки ниже:

public function onUserAuthenticate($credentials, $options, &$response)
{
	// No remember me for admin
	if ($this->app->isAdmin())
	{
		// cay127
		// return false;
	}

В коде отменяется стандартное ограничение джумлы, хотя функционал "Запомнить пароль" работает для любого раздела сайта одинаково.

Это не все, но объяснять уже не буду, слишком долго.

public function onUserAfterLogout($options)
{
	// No remember me for admin
	if ($this->app->isAdmin())
	{
		// cay127
		// return false;
	}

Далее еще. Кусок кода большой, нужно развернуть:

public function onUserAfterLogin($options)
{
	// No remember me for admin
	if ($this->app->isAdmin())
	{
		// cay127
		$options[ 'remember' ] = 1;
		// return false;
	}

	if (isset($options['responseType']) && $options['responseType'] == 'Cookie')
	{
		// Logged in using a cookie
		$cookieName		= JUserHelper::getShortHashedUserAgent();

		// We need the old data to get the existing series
		$cookieValue	= $this->app->input->cookie->get($cookieName);
		$cookieArray	= explode('.', $cookieValue);
		// Filter series since we're going to use it in the query
		$filter			= new JFilterInput;
		$series			= $filter->clean($cookieArray[1], 'ALNUM');
	}
	elseif (!empty($options['remember']))
	{
		// Remember checkbox is set
		$cookieName		= JUserHelper::getShortHashedUserAgent();

		// Create an unique series which will be used over the lifespan of the cookie
		$unique = false;
		do
		{
			$series = JUserHelper::genRandomPassword(20);

			$query = $this->db->getQuery(true)
				->select($this->db->quoteName('series'))
				->from($this->db->quoteName('#__user_keys'))
				->where($this->db->quoteName('series') . ' = ' . $this->db->quote($series));

			$results = $this->db->setQuery($query)->loadResult();

			if (is_null($results))
			{
				$unique = true;
			}
		}
		while ($unique === false);
	}
	else
	{
		return false;
	}

	// Get the parameter values
	$lifetime	= $this->params->get('cookie_lifetime', '60') * 24 * 60 * 60;
	$length		= $this->params->get('key_length', '16');

	// Generate new cookie
	$token		= JUserHelper::genRandomPassword($length);
	$cookieValue = $token . '.' . $series;

	// Overwrite existing cookie with new value
	$this->app->input->cookie->set(
		$cookieName, $cookieValue, time() + $lifetime, $this->app->get('cookie_path', '/'), $this->app->get('cookie_domain'), $this->app->isSSLConnection()
	);

	$query = $this->db->getQuery(true);

	// cay127
	$query = 'SELECT ' . $this->db->quoteName('id');
	$query .= ' FROM ' . $this->db->quoteName('#__user_keys');
	$query .= ' WHERE ' . $this->db->quoteName('series') . ' = ' . $this->db->quote($series);
	$query .= ' AND ' . $this->db->quoteName('user_id') . ' = ' . $this->db->quote($options['user']->username);

	$results = $this->db->setQuery($query)->loadObjectList();
	if (count($results) !== 0) {
		$b_update = true;
	} else {
		$b_update = false;
	}

	$query = $this->db->getQuery(true);
	// cay127 #

	// cay127
	// if (!empty($options['remember']))
	if ($b_update == false AND !empty($options['remember']))
	{
		// Create new record
		$query
			->insert($this->db->quoteName('#__user_keys'))
			->set($this->db->quoteName('user_id') . ' = ' . $this->db->quote($options['user']->username))
			->set($this->db->quoteName('series') . ' = ' . $this->db->quote($series))
			->set($this->db->quoteName('uastring') . ' = ' . $this->db->quote($cookieName))
			->set($this->db->quoteName('time') . ' = ' . (time() + $lifetime));
	}
	else
	{
		// Update existing record with new token
		$query
			->update($this->db->quoteName('#__user_keys'))
			->where($this->db->quoteName('user_id') . ' = ' . $this->db->quote($options['user']->username))
			->where($this->db->quoteName('series') . ' = ' . $this->db->quote($series))
			->where($this->db->quoteName('uastring') . ' = ' . $this->db->quote($cookieName));
	}

	$hashed_token	= JUserHelper::hashPassword($token);
	$query
		->set($this->db->quoteName('token') . ' = ' . $this->db->quote($hashed_token));

	$this->db->setQuery($query)->execute();

	return true;
}

Файл libraries/cms/application/administrator.php

И теперь самое, что может показаться странным, но джумла почему-то делает язык английским после окончания срока действия временной куки на час. Исправляем и это.

protected function initialiseApp($options = array())
{
	// cay127
	if ( $options[ 'language' ] == 'en-GB' ) {
		$options[ 'language' ] = '';
	}

В заключение

Все, можно наконец-то заняться кодингом, просмотром авто-обновлений статистики в режиме live и не переживать ни о чем.

Update 2014-04-06 

Что-то включил сегодня компьютер после сна и попал на форму логина:( Надеюсь не последнее добавление с языком повлияло таким образом, что меня стало выкидывать. Подумаю еще...

Update 2014-08-25 

Обновил джумлу, повторил все действия по своей инструкции и ничего не получилось. Видимо забыл еще один файл. Продолжаю.

plugins/system/remember/remember.php

1-е изменение:

public function onAfterInitialise()
{
	// No remember me for admin.
	if ($this->app->isAdmin())
	{
		// cay127
		// return;
	}

и 2-е:

public function onUserLogout($user, $options)
{
	// No remember me for admin
	if ($this->app->isAdmin())
	{
		// cay127
		// return true;

Короче всегда ищем "No remember me for admin" в консоли через grep и спасибо разработчикам за комментарии.

Tags: , , ,
Записано в Joomla, Программирование    |    Постоянная ссылка

Решение проблем с NGINX, IP и HTTPS в Joomla 3.2.3

Апрель 5, 2014

Этот пост будет первым из серии "Танцы с бубном в Joomla". Почему так? Несмотря на все достоинства среды, возникают проблемы, которые приходится внедрять с помощью внедрения своего кода в начинку самой джумлы, что не есть хорошо, но все же. Собственно это и есть одна из причин поста - сохранить изменения. В коде помечаю такие места с помощью комментария "// cay127" и команда grep мне всегда поможет быстро найти все, что было изменено вручную.

И еще пару слов - да, где-то может плагин был бы лучшим решением, может где-то не докопал до истины, но просто экономил время. Плагин отмечу - не всегда применим и это скоро станет понятно.

После вступления

Проблема вот в чем - джумла строит ссылки следующим образом (автоматически):

$theURI = 'http' . $https . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

Но у меня переменная $_SERVER['HTTP_HOST'] содержит IP адрес, а не название домена вовсе. Т.о. быстрое решение стало следующим: правим файл:

libraries/joomla/uri/uri.php

точка опоры:

public static function getInstance($uri = 'SERVER')

Без лишних подробностей изменения (помним о комментарии):

public static function getInstance($uri = 'SERVER')
{
	if (empty(self::$instances[$uri]))
	{
		// Are we obtaining the URI from the server?
		if ($uri == 'SERVER')
		{
			// Determine if the request was over SSL (HTTPS).
			// cay127
			if (true OR sset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) != 'off'))
			{
				$https = 's://';
			}
			else
			{
				$https = '://';
			}

			/*
			 * Since we are assigning the URI from the server variables, we first need
			 * to determine if we are running on apache or IIS.  If PHP_SELF and REQUEST_URI
			 * are present, we will assume we are running on apache.
			 */

			if (!empty($_SERVER['PHP_SELF']) && !empty($_SERVER['REQUEST_URI']))
			{
				// To build the entire URI we need to prepend the protocol, and the http host
				// to the URI string.

				// cay127
				// $theURI = 'http' . $https . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
				// [HTTP_HOST] => 212.XX.XX.XX
				$theURI = 'http' . $https . 'www.site.ru' . $_SERVER['REQUEST_URI'];
			}

Реальный IP и домен скрыты, но суть ясна. Плюс прописал условие всегда использовать только HTTPS.

Tags: , , , , , ,
Записано в Joomla, Программирование    |    Постоянная ссылка

Логирование в Joomla 1.7 с помощью JLog

Май 24, 2012

Для того, чтобы вести логирование в Joomla, достаточно добавить следующий код:

// log save
jimport('joomla.error.log');

$log = JLog::getInstance('activity_saves.php');

$entry = array(
	'comment' => 'Activity ' . $this->activity_id . ' modified by ' . JFactory::getUser()->name
);

$log->addEntry($entry);

При вызове функции или исполнении файла с вставленным кодом будет создан файл с логом activity_saves.php в папке logs.

Лог будет следующего вида:

#
#<?php die('Forbidden.'); ?>
#Date: 2012-05-24 14:50:29 UTC
#Software: Joomla Platform 11.2.0 Stable+Modified [ Omar ] 27-Jul-2011 00:00 GMT

#Fields: date	time	priority	clientip	category	message
2012-05-24	14:50:29	INFO	127.0.0.1	-	Activity 1 modified by Super User
2012-05-24	14:50:39	INFO	127.0.0.1	-	Activity 2 modified by Super User
2012-05-24	14:50:41	INFO	127.0.0.1	-	Activity 3 modified by Super User
2012-05-24	15:35:31	INFO	127.0.0.1	-	Activity 2 modified by Super User
2012-05-24	15:35:41	INFO	127.0.0.1	-	Activity 2 modified by Super User
2012-05-24	15:35:44	INFO	127.0.0.1	-	Activity 2 modified by Super User
2012-05-24	15:56:01	INFO	127.0.0.1	-	Activity 1 modified by secondadmin
2012-05-24	15:56:05	INFO	127.0.0.1	-	Activity 1 modified by secondadmin

Tags: , , , , , ,
Записано в Joomla, Программирование    |    Постоянная ссылка