Laravel по-русски

Русское сообщество разработки на PHP-фреймворке Laravel.

Ты не вошёл. Вход тут.

#1 13.05.2015 12:10:53

Очень сложный вопрос по авторизациям в Ларе

Есть нормально работающая авторизация/Регистрация + Вход через социалки. Тут всё отлично.

Необходимы действительно полезные советы, если нечего говорить, то и не стоит. Извините за прямоту.

Нужно сделать Multiple Authorization как у гугла/яндекса.

То есть, войди пользователем 1, добавить пользователя 2, 3, 4, .....

Чтобы впоследствии было возможным переключаться между ними в 1 клик.

Так же данные об этих (дополнительных, неактивных) пользователях должны быть доступны каким-либо образом, чтобы получать их уведомления либо другую инфу, не требующую создание контента.

При этом необходимо учесть безопасность аккаунта(ов), чтобы нельзя было перехватить логин/пароль (в плане хранения данных на стороне клиента, процесс передачи данных на каком-либо протоколе пока не волнует).

Есть какие-то мысли???

Не в сети

#2 13.05.2015 12:25:01

Re: Очень сложный вопрос по авторизациям в Ларе

В чём сложность? Все данные о вторичных входах хранятся в сессии (что это за данные зависит от задачи — можно просто список ID пользователей). Если надо читать оповещания всех пользователей — значит, в дополнение к Auth::user() страница должна перебирать вторичные логины в сессии. Переключение делается ручным входом, как тут.

  1. При этом необходимо учесть безопасность аккаунта(ов)

Безопасность входа нескольких аккаунтов не отличается от безопасности одного — если безопасно хранить ID текущего пользователя в сессии, значит одинаково безопасно хранить и несколько таких ID.

Не в сети

#3 13.05.2015 12:55:03

Re: Очень сложный вопрос по авторизациям в Ларе

Proger_XP пишет:

В чём сложность? Все данные о вторичных входах хранятся в сессии (что это за данные зависит от задачи - можно просто список ID пользователей). Если надо читать оповещания всех пользователей - значит, в дополнение к Auth::user() страница должна перебирать вторичные логины в сессии. Переключение делается ручным входом, ((https://laravel.ru/docs/v4/security#%D1%80%D1%83%D1%87%D0%BD%D0%B0%D1%8F как тут)).

> При этом необходимо учесть безопасность аккаунта(ов)
Безопасность входа нескольких аккаунтов не отличается от безопасности одного - если безопасно хранить ID текущего пользователя в сессии, значит одинаково безопасно хранить и несколько таких ID.

По порядку.
1. А вот сам попробуй сделать вход, затем открой страницу логина, если получится...
1.1 Потом попробуй компилятором рест-запросов (плагин у браузера) протолкнуть пост в логин, а потом, когда успешно вошёл, второй раз.
1.2 Править код в /vendor желания нет, как бы
2. Сложность в том, что не представления, как
а) войти вторично
б) переключаться между авторизованными пользователями без передачи каких-либо данных типа логин/пароль.

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

За ответ спасибо, но это не совет.

Изменено hzone (13.05.2015 12:55:33)

Не в сети

#4 13.05.2015 13:01:12

Re: Очень сложный вопрос по авторизациям в Ларе

А нет чтобы подумать свой головой, хочется сразу готового решения на блюдечке?

  1. А вот сам попробуй сделать вход, затем открой страницу логина, если получится…

Во-первых, страницу входа ты делаешь сам, и как сделаешь — так и откроется. Во-вторых, описанная мной схема отлично подходит под авторизацию в Laravel — первичный вход делается штатными средствами через Auth::attempt() и пр., таким образом ничего менять не нужно. Вторичный вход делается через твою собственную страницу, которая вместо или в дополнение к изменению Auth::user() изменяет переменную в сессии, где хранятся вторичные ID.

  1. переключаться между авторизованными пользователями без передачи каких-либо данных типа логин/пароль.

Делается отдельная страница, которая принимает на вход ID вторичного пользователя, проверяет его наличие в переменной сессии и если он есть — делает ручной вход по ссылке в моём сообщении выше.

  1. вот почему-то большинство не думает над проблемой, работают мозгом на уровне интерфейса, а не кода.

Скорее потому что кто-то не думает над проблемой вообще, и подсказки расценивает как доказательство своего превосходства.

Рисуйте блок-схемы сами. Это форум программистов, а не доска студенческой взаимопомощи.

Не в сети

#5 13.05.2015 13:35:18

Re: Очень сложный вопрос по авторизациям в Ларе

Proger_XP пишет:

А нет чтобы подумать свой головой, хочется сразу готового решения на блюдечке?

> А вот сам попробуй сделать вход, затем открой страницу логина, если получится...
Во-первых, страницу входа ты делаешь сам, и как сделаешь - так и откроется. Во-вторых, описанная мной схема отлично подходит под авторизацию в Laravel - первичный вход делается штатными средствами через Auth::attempt() и пр., таким образом ничего менять не нужно. Вторичный вход делается через твою собственную страницу, которая вместо или в дополнение к изменению Auth::user() изменяет переменную в сессии, где хранятся вторичные ID.

> переключаться между авторизованными пользователями без передачи каких-либо данных типа логин/пароль.
Делается отдельная страница, которая принимает на вход ID вторичного пользователя, проверяет его наличие в переменной сессии и если он есть - делает ручной вход по ссылке в моём сообщении выше.

> вот почему-то большинство не думает над проблемой, работают мозгом на уровне интерфейса, а не кода.
Скорее потому что кто-то не думает над проблемой вообще, и подсказки расценивает как доказательство своего превосходства.

Рисуйте блок-схемы сами. Это форум программистов, а не доска взаимопомощи.

По порядку:
- Да, логично не изобретать велосипед. Если есть готовое решение, то любой здравомыслящий человек его будет использовать.
- То есть идея в том, чтобы (повторю) в 1й раз использовать штатный логин, затем использовать тот же Auth::attempt() с хранением результата работы в сессии (активные авторизации) и в БД, с коими и сверяться при переключении.
ОК. посоветуй пожалуста:
- что должно произойти, если я переключаюсь, если необходимо сублогин №842 сделать основным №1, а текущий (основной №1) сместить на вторичную позицию (положение не важно, просто сделать вторичным, впоследствии выбираемым)...
Мне не совсем всё понятно, что нужно сделать без последствий потери текущей сессии.
Опять Auth::attempt( №842 ) на позицию основного и повторить Auth::attempt( №1) на позицию вторичного ?

Я правильно понял идею ?

Не слетит ли сессия (пока обсуждаем теорию) или не произойдёт ли побочных проблем ?

Не в сети

#6 13.05.2015 13:45:29

Re: Очень сложный вопрос по авторизациям в Ларе

В догонку, как представляешь себе сторону БД ?
Ведь необходима таблица с данными вторичных авторизаций, относительно основной авторизации для восстановления данных сессии, если таковая по какой-то причине отсутствует.
Хранить user_id <=> user_id? как бы масло масленное.
Хех, проблема в том, что не ясно что с чем связать, если всё динамично двигается smile
(сессии в бд храню), да, думал связать с сессиями, но вдруг необходимо будет сессии в мемкеш выбросить... уже сложнее, а я не ищу сложных путей wink

Изменено hzone (13.05.2015 13:47:30)

Не в сети

#7 13.05.2015 16:42:59

Re: Очень сложный вопрос по авторизациям в Ларе

Auth::atempt() перебивает сессию новой авторизацией.
в принципе не страшно.
- берём старого auth::user() в переменную
если аттемпт успешный, то пихаем в массив суб-логинов.
если нет, то аттемптим сохранённую запись взад.
активной становится та авторизация, что успешна.
= и бага и фича.

Auth::validate() возвращает булеан, не удобно. могли бы вернуть пользователя или нул.

т.е. штатными средствами сделать можно, но будет не кошерно.
и обидно что общая авторизация уже завершена и менять её себе во вред ((

остался вопрос - как хранить суб-логины (объеты User)


сессии не импонируют...

идеи есть?

Изменено hzone (13.05.2015 16:46:17)

Не в сети

#8 13.05.2015 20:17:35

Re: Очень сложный вопрос по авторизациям в Ларе

Теперь похоже на хоть какой-то поток собственных мыслей.

  1. Auth::validate() возвращает булеан, не удобно. могли бы вернуть пользователя или нул.
  2. т.е. штатными средствами сделать можно, но будет не кошерно.

Что не кошерно? Лишний запрос — возможно, но это не повод придумывать какие-то хитроумные схемы для решения простой задачи.

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

  1. Некто не авторизован. Заходит на твою страницу логина, вводит имя, пароль, отправляет форму. Делаешь Auth::attempt(). Если данные правильные — клиент становится авторизованным, причём список вторичных входов у него пустой (так как сессия была пустая).
  2. На каком-то этапе он хочет войти снова, под другими данными, оставив свой первый вход в списке вторичных входов. Для этого он переходит на другую страницу логина (это может быть тот же URL, но внутренне другая) — тоже вводит имя и пароль. Отправляет форму.
    1. Смотришь, верные ли данные. Для этого вызываешь Auth::validate().
    2. Если вход успешный (пункт a.) — заводишь в сессию новую переменную-массив со списком уже произведённых успешных входов (вторичных). Туда вставляешь старого пользователя, т.е. того, который на данный момент возвращается из Auth::user()->id.
    3. В конце концов вызываешь Auth::login(). Таким образом ты заменяешь активного пользователя на того, данные которого были переданы в форме (пункт 2.), а предыдущего сохраняешь в сессии. Здесь надо посмотреть, если login() как-то затирает сессию (чего быть не должно) — список вторичных надо сохранить и потом восстановить, благо всё это делается в рамках одного запроса.
  3. Клиент захотел зайти под другим пользователем, под которым он уже авторизовывался? Аналогично — помещаешь активного пользователя в массив вторичных, вызываешь Auth::login() на вторичном и получаешь нового пользователя со старой сессией, в том числе сохраняя список вторичных входов.

Не в сети

#9 14.05.2015 14:37:12

Re: Очень сложный вопрос по авторизациям в Ларе

я уже всё реализовал
всё реализовыватся на уровне процедуры переключения + миддлваря.
по порядку:
Роутер

Route::get('/subauth',			'SubAuthController@getSubauth');
Route::get('/subauth/switch/{uid}',	'SubAuthController@getSwitch');
Route::get('/subauth/logout/{uid}',	'SubAuthController@getLogout');
Route::get('/subauth/list/{uid}',	'SubAuthController@getList');
Route::get('/subauth/unlist/{uid}',	'SubAuthController@getUnlist');
Route::post('/subauth/login',		'SubAuthController@postLogin');

Контроллер

namespace App\Http\Controllers;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Contracts\Auth\Guard;
use Input;
use Auth;
use App\User;
use Redirect;
use URL;
use Session;
use View;

class SubAuthController extends Controller
{
	/**
	 * Конструктор
	 *
	 * @param \Illuminate\Contracts\Auth\Guard $auth
	 * @param \Illuminate\Http\Request         $request
	 */
	public function __construct( Guard $auth, Request $request )
	{
		$this->auth = $auth;
		$this->request = $request;
		$this->middleware( 'auth' );
	}

	/**
	 * страница с суб-авторизацией, списком вторичных пользователей, управление ими
	 */
	public function getSubauth()
	{
		// показываем вьюшку
		return View('subauth/index');
	}
	
	/**
	 * Пытаемся авторизовать вторичного пользователя
	 */
	public function postLogin()
	{
		// запоминаем основного/текущего пользователя, который встанет вниз списка вторичных пользователей.
		$old_user = Auth::user();
		// условия поиска пользователя
		$credentials = [
			'email'    => Input::get('email'),
			'password' => Input::get('password')
		];
		// логиним нового пользователя как основного <= и бага и фича. если хотите сидеть на одном, добавляя других - кода будет в 3-5 раз больше.
		if ( $this->auth->attempt($credentials) )
		{
			// извлечение вторичных пользователей из сессии
			$subLogins = Session::get('subLogins', []);
			// вставка сохранённог, уже бывшего основного/текущего пользователя, в список вторичных пользователей
			$subLogins[$old_user->id] = [
				'is_listed' => (count($subLogins)>4) ? false: true,
				'down_shifted' => time(),
				'user' => $old_user,
			];
			// сохранение вторичных пользователей
			Session::set('subLogins', $subLogins);
			// уход
			return Redirect::back();
		}
		else
		{
			// возврат старого пользователя с сообщением об ошибке
			$this->auth->login($old_user);
			return Redirect::back()
				->withErrors( trans('login.user_not_found') );
		}
	}

	/**
	 * переключает пользователя на вторичного, делая основным/текущим
	 *
	 * @param null $uid
	 *
	 * @return $this|\Illuminate\Http\RedirectResponse
	 */
	public function getSwitch($uid=null)
	{
		// запоминаем основного/текущего пользователя, который встанет вниз списка вторичных пользователей.
		$old_user = Auth::user();
		// извлечение вторичных пользователей из сессии
		$subLogins = Session::get('subLogins', []);
		// проверка на наличие запрашиваемого авторизованного пользователя
		if ( !empty( $subLogins ) && isset( $subLogins[$uid] ) )
		{	// НАШЛИ
			// удаление включаемого пользователя из вторичного списка пользователей
			unset( $subLogins[$uid] );
			// Грузим пользователя
			$User = User::find( $uid );
			// проверка пользователя
			if ( empty( $User ) )
			{
				// НЕ НАШЛИ
				// выход с сообщением об ошибке
				return Redirect::back()
					->withErrors( trans('login.user_not_found') );
			}
			else
			{
				$this->auth->login( $User );
				// вставка сохранённог, уже бывшего основного/текущего пользователя, в список вторичных пользователей
				$subLogins[$old_user->id] = [
					'is_listed' => (count($subLogins)>4) ? false: true, // фишка держать 5 приоритетных пользователей в некоеом списке быстрого доступа
					'down_shifted' => time(), // дата отключения (внесения во вторичных пользователей)
					'user' => $old_user,
				];
				// сохранение вторичных пользователей
				Session::set('subLogins', $subLogins);
				// уход
				return Redirect::back();
			}
		}
		else
		{
			// пустой массив вторичных пользователей, их нет
			// выход с сообщением об ошибке
			return Redirect::back()
				->withErrors( trans('login.users_not_found') );
		}

	}

	/**
	 * удаляет вторичного пользователя
	 *
	 * @param null $uid
	 *
	 * @return \Illuminate\Http\RedirectResponse
	 */
	public function getLogout($uid=null)
	{
		// извлечение вторичных пользователей из сессии
		$subLogins = Session::get('subLogins', []);
		// проверка на наличие запрашиваемого авторизованного пользователя
		if ( !empty( $subLogins ) && isset( $subLogins[$uid] ) )
		{	// НАШЛИ - удаляем
			unset($subLogins[$uid]);
			// сохранение вторичных пользователей
			Session::set('subLogins', $subLogins);
		}
		// уход
		return Redirect::back();
	}
	
	/**
	 * делает вторичного пользователя видимым в списке переключения (список быстрого доступа)
	 *
	 * @param null $uid
	 *
	 * @return \Illuminate\Http\RedirectResponse
	 */
	public function getList($uid=null)
	{
		// извлечение вторичных пользователей из сессии
		$subLogins = Session::get('subLogins', []);
		// проверка на наличие запрашиваемого авторизованного пользователя
		if ( !empty( $subLogins ) && isset( $subLogins[$uid] ) )
		{	// НАШЛИ - изменяем
			$subLogins[$uid]['is_listed'] = true;
			// сохранение вторичных пользователей
			Session::set('subLogins', $subLogins);
		}
		// уход
		return Redirect::back();
	}

	/**
	 * делает вторичного пользователя видимым только на странице управления
	 *
	 * @param null $uid
	 *
	 * @return \Illuminate\Http\RedirectResponse
	 */
	public function getUnlist($uid=null)
	{
		// извлечение вторичных пользователей из сессии
		$subLogins = Session::get('subLogins', []);
		// проверка на наличие запрашиваемого авторизованного пользователя
		if ( !empty( $subLogins ) && isset( $subLogins[$uid] ) )
		{	// НАШЛИ - изменяем
			$subLogins[$uid]['is_listed'] = false;
			// сохранение вторичных пользователей
			Session::set('subLogins', $subLogins);
		}
		// уход
		return Redirect::back();
	}
	
}

Middleware

<?php namespace App\Http\Middleware;

use Closure;
use View;
use Session;
use Auth;

class UserSwitcher
{
	/**
	 * сбрасываем вторичных пользователей (если есть) в сессию
	 *
	 * @param          $request
	 * @param callable $next
	 *
	 * @return
	 */
	public function handle($request, Closure $next)
	{
		if ( Auth::check() )
		{
			$subLogins = Session::get('subLogins', []);
			View::share( 'subLogins', $subLogins );
		}
		return $next($request);
	}

}

View'шку сами придумывайте )))

Изменено hzone (14.05.2015 14:42:23)

Не в сети

#10 14.05.2015 14:38:38

Re: Очень сложный вопрос по авторизациям в Ларе

и Proger_XP, давай без нервов ))) поуважительней - люди разные с разным уровнем знаний в конкретных областях.
За участие - спасибо!
Мозговой штурм удался на славу smile

Не в сети

#11 14.05.2015 22:08:47

Re: Очень сложный вопрос по авторизациям в Ларе

  1. и Proger_XP, давай без нервов )))

Ты сам посмотри, как написан твой второй пост. С таким отношением желание помогать пропадает сразу.

Поздравляю, реализовал по той самой схеме, что я описывал. Уверен, что выложенный код ещё кому-то пригодится.

Не в сети

#12 14.05.2015 22:17:01

Прохожий

Re: Очень сложный вопрос по авторизациям в Ларе

Первая функция тролля, - обозвать соседа троллем !
Топикстартер, иди на laravel.io там адекватов больше !

#13 14.05.2015 22:19:49

Re: Очень сложный вопрос по авторизациям в Ларе

Тема закрыта, во избежание.

Не в сети

Подвал раздела