Jump to content

Внешняя авторизация и запрет регистрации

Featured Replies

Всем доброго времени суток.
Меня зовут Юрий, и я хотел бы поделиться своим опытом настройки внешней авторизации в 4-ой версии форума.

Предисловие
Вот решил, обновить свой форум с 3.4.6 до 4.1.8. Естественно всё делаю на тестовом сервере, со всеми бэкапами. Обновился без ошибок, русифицировал. После всего начал играться с внешней авторизацией. Внешняя авторизации должна быть обязательна (форум для проекта с онлайн игрой), чтоб на форум могли заходить только игроки. В общем нашёл я нужные файлы, но код в них (ну естественно) совершенно отличный от старой версии. С горем пополам я разобрался во внешней авторизации. На третьей версии форума я не разбирался - мне досталась уже готовая внешняя авторизация, как раз под мои нужды.

Может я сейчас расскажу что-то банальное из серии "открыть Америку", но может кому-то принесу пользу, своим сообщением. Те кто разобрался во внешней авторизации сам, либо проходите мимо, либо, если есть ошибки у меня - поделитесь своим мнением. ;)

В чём плюсы новой внешней авторизации?
Ну во-первых. теперь всё в одном файле, не в двух, как было раньше. Если в 3-е версии, чтоб добавить новый способ шифрования пароля, надо было изменять два файла, то в 4-ой это всё в одном файле. Да и вообще, все файлы с авторизацией теперь в одном каталоге, что весьма упрощает работу с авторизацией.
Во-вторых, сам код стал более понятным для восприятия.
Но самым главным плюсом для меня оказалась возможность выбора типа аутентификации. В третьей версии, на чистом движке была возможность аутентификации только по имени. Но в моём случае, имя пользователя может измениться, в отличии от E-mail, поэтому я делал аутентификацию по E-mail. Для этого мне надо было редактировать файл внешней авторизации таким образом, чтоб он как имя использовал другое поле из внешней БД. Делалось легко, но всё же приходилось это делать ручками. Но вот вышла 4-я версия, и тут это уже встроено в движок форума. Ура, товарищи!

Как же настроить новую внешнюю авторизацию?
Я расскажу на своём примере, с добавлением дополнительного способа шифрования пароля.
Итак, находим файл '/system/Login/External.php'. Далее ищем строку 141, функцию encryptedPassword(). В конструкцию switch добавляем секцию case с нашим способом шифрования. В моём случае, это crypt с солью:

case 'crypt':
	return crypt($password, '$ra$05$rZMc8a8HnXT3R2lKTcFgaT$');

Далее, в функции acpForm() находим ключ массива db_encryption. Если ваша секция case состоит из двух строк, как у меня, и отделена от остальных конструкций разрывом строки, как в оригинале, то этот ключ будет находиться на 195-й строке. db_encryption является ассоциативным массивом с парой ключ => значение, где "ключ", это значение, указанное в вашей секции case, а "значение", это текст, который будет отображаться в АЦП, при выборе способа шифрования. Вот готовый код, с нашим способом шифрования:

'db_encryption'	=>  new \IPS\Helpers\Form\Select( 'login_external_encryption', $this->settings['db_encryption'], TRUE, array( 'options' => array(
	'md5'		=> 'MD5',
	'sha1'		=> 'SHA1',
	'crypt'		=> 'CRYPT',
	'plaintext'	=> 'login_external_encryption_plain',
) ) ),


Теперь, чтобы задействовать этот способ авторизации, вы идёте в АЦП -> Система -> Настройка сайта -> Методы входа. Включаете Внешняя база данных и переходите к её изменению. Настройте её по своему желанию, укажите поля E-mail и имени пользователей и выберите ваш способ шифрования пароля, который мы добавили в файл External.php. Сохраняем и отключаем внутреннюю авторизацию, под названием "Стандартный" (метод входа, имеется ввиду ;)).
Внешняя авторизация настроена и готова к использованию. Но это ещё не всё, как оказалось. Во всей этой красоте есть ложка мёда. Тьфу ты.. Ложка дёгтя. ;)

Самый большой минус, на мой взгляд (и единственный, замеченный мною), в новой системе внешней авторизации.
Этот минус больше связан с регистрацией, нежели авторизацией. В 3-ей версии форума было два режима отключения регистрации:

  1. Только внутренняя
  2. Все возможные методы регистрации

Всем понятно, что они значат. Первый режим позволяет создавать новых пользователей при использовании внешней авторизации, а вот второй режим блокирует всё. И эта реализация была правильной, на мой взгляд. Например, в моём случае форум используется только для зарегистрированных игроков в игре. Поэтому я отключаю внутреннюю регистрацию, чтоб могли зарегистрироваться только игроки, при использовании внешней авторизации (напомню, что внутренняя у нас отключена). А вот в 4-ке нас ждёт разочарование! :(
Дело в том, что в новой версии убрали "режимы" отключения регистрации. Теперь, если вы отключаете регистрацию, то даже используя внешнюю авторизацию, создать нового пользователя невозможно.

Решение проблемы с закрытой регистрацией и внешней авторизацией
Вполне возможно, что кто-то напишет хук, который фиксит эту проблему (если такие хуки возможны - я плохо разбираюсь в принципе их работы, только использую :lol: ), а может, уже такой хук есть. Я не знаю. Я эту проблему решил своим методом - напрямую изменив исходный код форума.
Дело в том, что проверка на то, отключена ли регистрация, происходит в самой функции регистрации. Моя идея состоит в том, чтобы проверять метод авторизации, при вызове функции регистрации, и, если это "внешняя авторизация", то разрешать регистрацию.
Идём в уже знакомый нам файл '/system/Login/External.php' и ищем строку 128. Там находится вызов функции регистрации.

$member = $this->createOrUpdateAccount( NULL, array(), $this->settings['db_col_user'] ? $result[ $this->settings['db_col_user'] ] : NULL, $this->settings['db_col_email'] ? $result[ $this->settings['db_col_email'] ] : NULL );

Забегая наперёд, эта функция, находящаяся в другом файле, по умолчанию принимает 7 параметров, а если их нет, то этим параметрам присваиваются нулевые значения (кроме первого, первый параметр должен обязательно передаваться, хотя бы нулевым). А наш вызов, на строке 128, передаёт всего 4 параметра: пользователя (пустой), настройки пользователя (тоже пустые), имя пользователя и его E-mail. Чтобы указать, что это именно "внешняя авторизация", нам достаточно передать один единственный параметр, со значением 'external' (так как это текстовое значение, не забываем ставить кавычки). Но учитывая то, что функция принимает 7 параметров, мы рискуем передать наше значение в другой параметр, и на выходе получить ошибку. Поэтому нам надо заполнить вызов функции дефолтными значениями оставшихся параметров и добавить наш параметр. Вот готовый код вызова функции регистрации (строка 128):

$member = $this->createOrUpdateAccount( NULL, array(), $this->settings['db_col_user'] ? $result[ $this->settings['db_col_user'] ] : NULL, $this->settings['db_col_email'] ? $result[ $this->settings['db_col_email'] ] : NULL, NULL, NULL, NULL, 'external' );

Теперь надо принять наш параметр в самой функции регистрации. Открываем файл '/system/Login/LoginAbstract.php'. Этот файл содержит основные функции, касающиеся авторизации, регистрации и удаления пользователей (удаление вызывается из родительского класса). На строке 267 находим функцию createOrUpdateAccount() и дописываем наш параметр, с дефолтным значением 'internal' (так как все остальные вызовы этой функции не передают этот параметр, то дефолтное значение обязательно). Я дописал такой вот код $reg_method = 'internal'.

protected function createOrUpdateAccount( $member, $memberProperties=array(), $name=NULL, $email=NULL, $details=NULL, $profileSync=NULL, $profileSyncClass=NULL, $reg_method = 'internal' )

Чуть ниже, на строке 272 находим проверку на отключение регистрации:

/* Is registration enabled? */
if( !\IPS\Settings::i()->allow_reg )
{
	$exception = new \IPS\Login\Exception( 'reg_disabled', \IPS\Login\Exception::REGISTRATION_DISABLED );
	$exception->handler = mb_substr( get_called_class(), 10 );
	$exception->member = $member;
	throw $exception;
}

Мы должны в условие добавить наш параметр. Так как данная конструкция прерывает выполнение кода, а нам надо, чтоб была доступна только внешняя регистрация, при отключенной регистрации, то, для срабатывания прерывания, то метод регистрации не должен быть внешним. Код с исправленным условием:

/* Is registration enabled? */
if( !\IPS\Settings::i()->allow_reg && $reg_method != 'external')
{
	$exception = new \IPS\Login\Exception( 'reg_disabled', \IPS\Login\Exception::REGISTRATION_DISABLED );
	$exception->handler = mb_substr( get_called_class(), 10 );
	$exception->member = $member;
	throw $exception;
}

Ну вот и всё. Теперь ваша внешняя авторизация не подчиняется правилу отключённой регистрации. По такому принципу вы можете в любых других методах регистрации указать, какой можно использовать при отключённой регистрации, а какой нельзя.

Надеюсь, для кого-то моя статья будет полезна. Если есть какие-то замечания по поводу моей статьи - обязательно напишите, я из обязательно учту на будущее. :)
Всего вам наилучшего, и приятной работы с новой версией форума.

Link to comment
https://ipbmafia.ru/topic/13792-vneshnyaya-avtorizaciya-i-zapret-registracii/
Share on other sites

Так как редактировать сообщения я не могу, то новым сообщением добавлю, я забыл сказать, что кнопку "Регистрация" вам надо будет ручками выпилить из 'globalTemplate', если мне не изменяет память, в настройках стилей и тем.

P.S.: что-то мне подсказывает, что я тему не в той ветке создал. :(

9 минут назад, intro сказал:

Так как редактировать сообщения я не могу, то новым сообщением добавлю, я забыл сказать, что кнопку "Регистрация" вам надо будет ручками выпилить из 'globalTemplate', если мне не изменяет память, в настройках стилей и тем.

P.S.: что-то мне подсказывает, что я тему не в той ветке создал. :(

Скорее всего это надо было запостить в документации :D

Ну да лан, ниче) Но тема довольно-таки объемная и интересная

23 часов назад, MrHaack сказал:

Скорее всего это надо было запостить в документации

Вот и я об этом же подумал, но запоздало. Сначала мне показалось, что там переведённые офф. доки . :)

23 часов назад, MrHaack сказал:

Ну да лан, ниче) Но тема довольно-таки объемная и интересная

Спасибо. :$

22 часов назад, intro сказал:

Если в 3-е версии, чтоб добавить новый способ шифрования пароля, надо было изменять два файла, то в 4-ой это всё в одном файле.

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

 

23 часов назад, intro сказал:

Во-вторых, сам код стал более понятным для восприятия.

Это в четверке что-ли? Более ебанутого для восприятия кода чем в этом паттерне программирования а ля "ооп джава" и которым в сейчас превратили все фреймворки в какое-то унылое говно я не встречал. Тройка на этот счет была более интуитивная в классическом стиле php. 

 

23 часов назад, intro сказал:

В третьей версии, на чистом движке была возможность аутентификации только по имени. Но в моём случае, имя пользователя может измениться, в отличии от E-mail, поэтому я делал аутентификацию по E-mail. Для этого мне надо было редактировать файл внешней авторизации таким образом, чтоб он как имя использовал другое поле из внешней БД.

Для этого нужно было только заменить $RDB->addSlashes($username) на $RDB->addSlashes($this->method_config['login_user_id'] == 'email' ? $email_address : $username), а все остальное настроить в АЦ: в опциях метода для Login Type указать Email address, а в его настройках указать поле емайла для Remote username name field. Больше руками ничего не надо было делать - при желании легко можно переключится с емайла на юзернейм в опциях метода указав соответствующий тип и имя поле в бд. 

 

В 05.03.2016 в 19:04, intro сказал:

Если ваша секция case состоит из двух строк, как у меня, и отделена от остальных конструкций разрывом строки, как в оригинале, то этот ключ будет находиться на 195-й строке.

You are serious? "А если там не будет перевода строк то она будет в строке 194. А если в вашем блоке присутствуют нестандартные типы шифрования то она будет строке 194 + %n, где %n это число ваших методов". Автор, в таких случаях просто пишут перед или после чего нужно добавить код, строку нет смысла указывать так как она может меняться от версии к версии и притом весьма значительно, указать можно только приблизительно. 

Слишком много букв о том, как добавить две строчки кода и что в старой версии для этого пришлось бы редактировать два файла. Такое ощущение что вы рассказываете не том как добавить новый тип шифрования, а закрепляете свои познания в php передачей аргументов в функции, в каком порядке они должны идти и как обрамляются строки. Тем, кто знаком с этим языком и так это знают, им нужен конкретно способ, а тем кто не знаком, эти подробности абсолютно не нужны.  Способ с передачей аргументов вообще лишней. У каждого метода есть свой ключ который можно использовать в условие:

if( !\IPS\Settings::i()->allow_reg AND mb_strtolower( $this->key ) !== 'external' )

Более того, даже этого делать не нужно, достаточно просто включить регистрацию перед вызовом createOrUpdateAccount:

			\IPS\Settings::i()->allow_reg = 1;

			$member = $this->createOrUpdateAccount( NULL, array(), $this->settings['db_col_user'] ? $result[ $this->settings['db_col_user'] ] : NULL, $this->settings['db_col_email'] ? $result[ $this->settings['db_col_email'] ] : NULL );

 

  • 2 years later...

На 4.3 перестало работать, в частности в файле LoginAbstract стала значительно меньше строк. Как реанимировать?

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.


Guest
Ответить в этой теме...

Последние посетители 0

  • No registered users viewing this page.