Laravel по-русски

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

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

#1 11.06.2013 12:39:06

[L4] Вход от имени другого пользователя

Всем привет!

Такой вопрос назрел - делаю систему авторизации. У меня есть несколько ролей, среди них админ. Мне нужно чтобы я от админа мог зайти под любым другим пользователем и выйти соотвественно. Если бы я использовал обычные сессии, то задача решается установкой id залогиненного юзера, и id админа (чтобы вернуться обратно). Но я пытаюсь использовать те средства что предоставляет laravel, и не очень понимаю как грамотно все сделать.

Во-первых у меня щас стоит время жизни сессии 0, т.е. по закрытию браузера сессия обнуляется.
Во-вторых у меня есть галка типа "Запомнить меня", $remember = true то бишь.

Одновременно писать
Auth::logout();
Auth::login(User::find($id));
нельзя, ругается с ошибкой.

Без logout-а вроде сработало, но если я проставлю Session::put('logged_from_admin', true) то после закрытия браузера я уже потеряю эту переменную. Можно убрать нулевое время, но тогда смысл в галке "Запомнить меня"

И я не очень понял разницу между login и loginUsingId (разве что один принимает модель, другой айдишник). С помощью второй ф-ии залогиниться не получилось вообще

Не в сети

#2 11.06.2013 12:42:20

Re: [L4] Вход от имени другого пользователя

Laravel 4?

  1. после закрытия браузера я уже потеряю эту переменную

Что мешает использовать cookie?

Не в сети

#3 11.06.2013 13:33:02

Re: [L4] Вход от имени другого пользователя

А что туда записать, типа logged_from_admin = true, admin_id = ... ?
И сделать кнопку если есть такая кука, по кнопке переходим на ф-ию где проверка опять же наличия куки, и если она есть - релогин из под admin_id?
Просто не хорошо же хранить такие данные в куках?

Да, laravel 4

Не в сети

#4 11.06.2013 14:03:29

Re: [L4] Вход от имени другого пользователя

Какая у тебя стоит задача? Админ зашёл на сайт, авторизовался как он сам, поставив флаг «Запомнить меня». Затем авторизовался как другой пользователь. Как ты хочешь сделать — чтобы админ при выходе снова стал собой или он стал обычным пользователем и может выйти, а затем снова зайти под своим паролем?

Зачем нужна logged_from_admin?

Не в сети

#5 11.06.2013 14:19:04

Re: [L4] Вход от имени другого пользователя

Админ зашел на сайт, авторизовался (либо с галочкой "запомнить меня" либо без неё, как решит). Ему вывелся список пользователей и рядом с каждым юзером иконка "войти от юзера". После того как он кликнул, он залогинелся от имени этого юзера и видит его админку + кнопку "вернуться назад от админа" по нажатию на которую он становится админом.

logged_from_admin чтобы отобразить кнопку. Ну можно без неё, просто проверять есть ли admin_id. Только меня смущает класть это в куки.

Не в сети

#6 11.06.2013 14:20:51

Re: [L4] Вход от имени другого пользователя

"чтобы админ при выходе снова стал собой" - да, вот так

Не в сети

#7 11.06.2013 16:44:49

Cheshirrski
masterМастер
Откуда: Днепр
Сообщений: 116
Статей: 2

Re: [L4] Вход от имени другого пользователя

Имхо, вы как-то не с той стороны заходите, у вас ролевая система - сделайте что-то вроде

if ( $role === 'admin' ){
//грузим необходимые данные пользователя
}

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

Не в сети

#8 11.06.2013 16:47:33

Re: [L4] Вход от имени другого пользователя

Потом звонит юзер и говорит "у меня что-то в админке цифры не те, можете посмотреть?", а я ему: "не, не могу, дайте пароль" smile

Не в сети

#9 11.06.2013 17:20:50

Cheshirrski
masterМастер
Откуда: Днепр
Сообщений: 116
Статей: 2

Re: [L4] Вход от имени другого пользователя

if ( $role === 'admin' ){
//грузим админку пользователя
//???
//PROFIT!!
}

Не в сети

#10 11.06.2013 17:46:01

Re: [L4] Вход от имени другого пользователя

У меня есть admin, есть client. У них разные админки. У каждого свой логин и пароль. Клиентов много, админ один.
If ($role =='admin') { грузим админку админа; }
if ($role == 'client') { грузим админку клиента; }

Но админ должен иметь возможность увидеть админку глазами клиента

Не в сети

#11 11.06.2013 18:19:34

Cheshirrski
masterМастер
Откуда: Днепр
Сообщений: 116
Статей: 2

Re: [L4] Вход от имени другого пользователя

function get_clientadminka ( $idclient ){

$data = Client::adminka($idclient );
return View::make( 'client.adminka' )->with( 'data', $data );

}

Не в сети

#12 11.06.2013 18:55:46

Re: [L4] Вход от имени другого пользователя

Etern1ty прав и такая проблема/usecase действительно есть. Наглядный пример — интернет-магазин, где есть админы (я), менеджеры и пользователи. Менеджеры видят список своих заказов, пользователи — своих, я как админ вижу их все. Возможности переключаться между видами нет. Зато есть возможность входа под любым пользователем, если это позволяют права — и это очень удобно, не нужно придумывать переключатели «смотреть как админ/пользователь» для каждой функции — один «sudo» покрывает их все.

Касательно сабжа. Раз у тебя сессия закрывается вместе с браузером логичнее всего использовать долгоживущую cookie, но вместо пароля или ещё какой-то закрытой информации хранить там ID админа (который стал пользователем) и хэшировать (подписывать) его твоим application.key. На самом деле Laravel (3 точно) уже сам подписывает cookie — открой Firebug и посмотри, любая cookie будет содержать перед своим значением строку с хэшем:

language = 9e237a356c34b1fa243e30b25bf92757422de286~ru

Если попытаешься изменить значение напрямую хэш не совпадёт и Laravel удалит её. Таким образом можешь хранить ID в открытую, не беспокоясь, что кто-то установит cookie — ему для этого нужно будет знать твой ключ. Для верности, чтобы хэш постоянно менялся, можешь добавлять второй хэш, зависящей от номера недели и года, к примеру — тогда человек не сможет подсмотреть хэш у вошедшего админа и использовать его у себя.

Не в сети

#13 13.06.2013 12:57:10

Re: [L4] Вход от имени другого пользователя

Как то так тогда что ли:

PHP
// Главная. Проверяем залогинен ли юзер
Route::get('/', function() {
    if (
Auth::check())
        
$user Auth::user();

                
// Если админ
        
if (Company::isSuperAdmin($user->company_id)) {
                        
// Достать юзеров которые не админы
            
$users User::join('settings''settings.value''!=''users.company_id')
                         ->
where('settings.name''=''admin_id')
                         ->
get();

            return 
View::make('admin')->with('users'$users);
        } else {
                        
// Если не админ то передаем куку sudoer. Если она есть, выводим ссылку "Вернутся к админу"
            
return View::make('client')->with('sudoer'Cookie::get('sudoer'))
                                       ->
with('email'$user->email);
        }
    } else {
        return 
View::make('login');
    }
});

Route::get('logout', function() {
    
Auth::logout();

        
// Если есть кука то удалить её (-1 время жизни)
    
if (Cookie::get('sudoer')) {
        
$sudoer Cookie::make('sudoer'false, -1);
        return 
Redirect::to('/')->withCookie($sudoer);
    } else {
        return 
Redirect::to('/');
    }
});

// Логинемся от админа под другим юзером
Route::get('loginAsUser/{id}', array('before' => 'superAdminJSON', function($id) {
    
$sudoer Cookie::make('sudoer'Auth::user()->id); // Кука с айди админа

    
Auth::login(User::find($id));

    return 
Redirect::back()->withCookie($sudoer);
}));

// Возвращаемся в админку из под админа
Route::get('returnToAdmin', function() {
    if (
Cookie::get('sudoer')) {
        
Auth::login(User::find(Cookie::get('sudoer')));
        return 
Redirect::back()->withCookie(Cookie::make('sudoer'false, -1)); // Удаляем куку
    
}
});

Я правильно понимаю что главное в куках это то что юзер не может ничего поменять, но если их типа украдут с компа то их можно будет использовать? Я попробовал в двух браузерах вручную скопировать содержимое кук и все сработало, но можно же приписывать user agent, айпи и т.п. внутри содержимого и тогда даже если её украсть нельзя будет её использовать ? (Ну, понятно что можно все подделать, но при этом айпи например нам неизвестен еже)

Изменено Etern1ty (13.06.2013 12:57:18)

Не в сети

#14 13.06.2013 13:18:14

Re: [L4] Вход от имени другого пользователя

  1. но если их типа украдут с компа то их можно будет использовать?

Да, об этом я писал выше.

  1. (Ну, понятно что можно все подделать, но при этом айпи например нам неизвестен еже)

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

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

Не в сети

#15 13.06.2013 15:47:00

Re: [L4] Вход от имени другого пользователя

А в laravel 4 я как вижу и так значения не хранятся в открытом виде:
sudoer = eyJpdiI6IjJsXC80aDQ5d3V4NE9aSlBmRDFxTjhySHJzUDQ5dzlsY0xJaGV4aDdoUDBRPSIsInZhbHVlIjoiXC9hVW5ybFRibUJUaHpHTXBuV0pKR1kzVDU2TW8zNmZKWEEwYkd3YURaaVU9IiwibWFjIjoiNjBlNTQ5MjdmOGZmNTFlM2M5NzRjN2I5Mjc4YWI5ZWJiZWFmYWJiY2U2NDE1NzkxODFjZGRjMjg0OTcwMGQ0MyJ9

Но если её в таком виде украсть то у юзера появится кнопочка «Зайти обратно к админу».

Я не очень понял насчет добавления даты. Т.е. например я сейчас кладу PHPCookie::make('sudoer'Auth::user()->id) типа айдишник админа. Ты предлагаешь класть что то вроде

PHP
Cookie::make('sudoer', array('created_at' => time(), 'expires_at' => time() + 60*60*24*7'admin_id' => $id);

И дальше когда достаешь куку проверять не сдохла ли она по времени и если да то регенерировать? Или как?)

Еще вопрос по терминологии — когда мы говорим о хешировании куки, подразумевается шифрование, т.е. там не md5 какой-нибудь, иначе мы бы не смогли достать данные из кук — верно? Используется именно шифрование по app.key

Изменено Etern1ty (13.06.2013 15:47:25)

Не в сети

#16 13.06.2013 16:36:49

Re: [L4] Вход от имени другого пользователя

  1. А в laravel 4 я как вижу и так значения не хранятся в открытом виде:

Может быть в L4, с ней не работал.

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

Как раз-таки хэширование, а не шифрование (двухстороннее). Всё проще: устанавливаешь cookie не PHP$id, а PHP$id.'-'.date('W'). В результате каждые 7 дней хэш будет меняться даже для одного и того же пользователя.

Не в сети

#17 14.06.2013 15:35:19

Re: [L4] Вход от имени другого пользователя

Если хеширование, то как мы можем получить в принципе значение кук, хеш на то и хеш что мы можем только сверить значение (юзер ввел пароль, мы его захешировали и сравнили хеш. а в куках мы напрямую получаем значение Cookie::get)

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

Я попробовал открыть 2 браузера, залогинется от имени юзера на одном, потом копирнул куки на другой. Вижу два одинаковых экрана. Потом на первом браузере разлогиневаюсь, прибавляю к куки рандом Cookie::make(’sudoer’, $id.’123123213’), залогиневаюсь обратно. Вижу тот же экран. И жму на обоих экранах «Вернутся к администратору» (по этой ссылке я просто вывожу значение айдишника админа). На одном я вижу айдишник админа, на другом айдишник админа + рандом. И там и там кука работает, просто лежит в ней разное

Не в сети

#18 16.06.2013 20:00:37

Re: [L4] Вход от имени другого пользователя

Принцип действия тот же, что и с хранением хэшей паролей вместо самих паролей. Если в cookie (без шифрования/подписывания Laravel, рассматриваем просто PHP) хранить любое значение, то его можно изменить и сервер об этом не узнает. В то же время, если там хранить то же самое значение плюс: PHP'~'.md5($value.'-random_string...-'.date('W')) — таким образом строка (значение cookie, видимое клиенту) будет значение~подпись-32-символа — при попытке изменить значение (часть до тильды) хэш (часть после тильды) перестанет совпадать. То есть при каждом считывании cookie сервер разделяет строку на значение и хэш, вычисляет хэш для строки и если он не совпадает с переданным — cookie менялась без ведома сервера, так как он бы подписал её верным хэшем, алгоритм вычисления которого он знает.

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

Не в сети

#19 17.06.2013 12:44:28

Re: [L4] Вход от имени другого пользователя

А, ну первый абзац я понял, да. Просто laravel 4 хранит куки не в виде «хеш~значение», я привел выше пример. Поэтому делаю вывод что куки хранятся в шифрованном а не хешированном виде (http://laravel.com/docs/security#encryption случаем не так?).

В моем случае получается я храню значение айдишника админа в виде: admin_id~date(’W’). Это значение лежит в зашифрованном виде (в любом случае его в фаербаге не видно никак, только рандомный набор символов). После этого, когда я получаю куку я разбиваю по тильде и смотрю день недели. Если он не равен текущем то куа не действительна?

Вот так?

PHP
        // Супер админ может залогинется от другого юзера
    
Route::group(array('before' => 'superAdminJSON'), function() {
        
Route::get('loginAsUser/{id}', function($id) {
            
$sudoer Cookie::make('sudoer'Auth::user()->id.'~'.date('W')); // Кука с днем недели
            
Auth::login(User::find($id));
            return 
Redirect::back()->withCookie($sudoer);
        });
    });


       
// .... Генерация вьюшки для обычного клиента

        
if (!Cookie::has('sudoer')) { // Если куки нет то нет
        
$sudoer false;
    } else {
        
$cookie explode('~'Cookie::get('sudoer')); // Если кука есть то разбиваем по тильде
        
$sudoer $cookie[1] === date('W') ? true false// Если неделя сегодняшняя то тру, иначе фолс
    
}
    return 
View::make('client')->with('sudoer'$sudoer)
                             ->
with('email'$user->email);

Не в сети

#20 17.06.2013 14:06:32

Re: [L4] Вход от имени другого пользователя

  1. (http://laravel.com/docs/security#encryption случаем не так?).

Если так то да, это двухстороннее шифрование и оно будет одинаковым для любого клиента.

  1. Если он не равен текущем то куа не действительна?

Да, ты фактически делаешь то, что делает L3.

Пример неверный с точки зрения хэша — ты ведь его нигде не вычисляешь, а просто сохраняешь номер недели. Другое дело, что если cookie шифруется, то можно не добавлять ещё и хэш, а просто добавлять случайное число (то, что я говорил в предыдущем посте предполагало, что у тебя строка хранится в открытом виде, как в L3). Это будет даже лучше, так как даже у одного пользователя в один и тот же день при входе/выходе cookie будет иметь разный вид.

Не в сети

#21 18.06.2013 12:08:53

Re: [L4] Вход от имени другого пользователя

Да, с точки зрения хеша md5(date(’W’)), ок.

Но про рандомную строку вовсе не понял: какой вид должна в итоге иметь кука? айди_админа~рандомная_строка?
У нас цель чтобы кука стала не действительна через какое то время после того как её украли. Хранится она в шифрованном виде.
Какую мне рандомную строку добавлять чтобы понять что через какой-то срок она не действительна? В случае с неделями я сравниваю номер недели.
Да, при генерации куки с md5(microtime()) (рандомная строка) при входе каждый раз разная кука, ну и что, если я её скопирую себе то она будет действительна, и я залогинюсь от админа

Не в сети

#22 22.03.2014 16:31:39

faracon

Re: [L4] Вход от имени другого пользователя

Товарищи знатоки - У меня такое предложение - а что если при каждом запросе генерировать новый ID сессий? - с пмощью функции
session_regenerate_id(); - Я пробовал - но вот только захешировать не получется! - т.к. session_regenerate_id(true); работает после session_start();
а session_id(); в котором можно задавать имя ID до - но я нашел всего 1 способ - это повторно отправить кукки с помощью функции setcookie(); НО это двойная работа - есть другие идеи?

#23 22.03.2014 17:11:42

Re: [L4] Вход от имени другого пользователя

А чем не нравится подход с хэшем? По-моему проще некуда.

Не в сети

#24 22.03.2014 19:37:42

faracon

Re: [L4] Вход от имени другого пользователя

Proger_XP пишет:

}%А чем не нравится подход с хэшем? По-моему проще некуда.

Ты не понял у меня стоит session_regenerate_id() гекоторый генерирует PHPSESSID (кукки) ПРИ КАЖДОМ ЗАПРОСЕ но я не могу его захешировать не получается - т.к. он работае только после session_start()! а session_id(здесь уникальный ID в MD5) наоборот работает только до  session_start()! единственый способ который я нашол  - это перезаписать кукки с помощью функции setcookie() - может знает кто как захешировать без использования функции setcookie()?

#25 24.03.2014 13:20:18

Ruzarh
Откуда: СПБ
Сообщений: 27

Re: [L4] Вход от имени другого пользователя

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

Да и плюс к этому, хорошо делать так, что бы к юзеру с админ правами другой не мог зайти (по мне это хороший тон).

Изменено Ruzarh (24.03.2014 13:22:41)

Не в сети

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