Авторизация в Laravel 5.3 из нескольких таблиц
Доброго времени суток. В данной статье мы рассмотрим, как реализовать авторизацию в Laravel из нескольких таблиц. Что я имею ввиду под авторизацией из нескольких таблиц? У нас есть три типа пользователей: гость, который не требует авторизации, пользователь, который имеет доступ в личный кабинет и администратор, который имеет доступ к админке. Так, вот два последних типа пользователей должны проходить авторизацию. Можно все это реализовать стандартными методами добавив, например, роль. Но иногда необходимо разделить пользователей и администраторов по разным таблица. Вот этот случай мы и рассмотрим.
Установку и настройку Laravel я пропущу.
Таблицы, миграции и модели.
Начнем с базы данных. В Laravel у нас есть две стандартные миграции:
- create_users_table – создает таблицу users для хранения пользователей
- create_password_resets_table – создает таблицу password_resets для хранения токенов, которые необходимы для сброса пароля
Отлично, для хранения обычных пользователей воспользуемся стандартной таблицей users. А для хранения администраторов будем использовать таблицу admins и чтобы не заморачиваться она будет аналогична таблице users. Давайте создадим миграцию create_admins_table. Для этого выполним команду:
php artisan make:migration create_admins_table
Миграцию create_admins_table создали, удаляем весь код в миграции. Теперь скопируем содержимое миграции create_users_table и вставим его в create_admins_table. Поправим немножко код (изменяем название класса и в методах up и down меняем название таблицы с users на admins) и вот, что у нас должно получиться:
<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateAdminsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('admins', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->string('email')->unique(); $table->string('password'); $table->rememberToken(); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('admins'); } }
Для администраторов сброс пароля не предусмотрен. Поэтому и таблица с токенами для админов нам не нужна.
Отлично теперь мы можем запустить наши миграции.
php artisan migrate
Проверим таблицы в базе. Для работы с базой данных я использую phpmyadmin
Отлично, наши таблицы созданы. Теперь нам необходимо создать модель для работы с таблицей admins из базы данных. Идем в консоль и выполняем следующую команду:
php artisan make:model Admin
Т.к. наши таблицы users и admins абсолютно идентичные, то и модели у них одинаковые. Теперь из модели Admin удаляем весь код. И вставляем в нее код из модели User с небольшими правками (меняем название класса):
<?php namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class Admin extends Authenticatable { use Notifiable; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'name', 'email', 'password', ]; /** * The attributes that should be hidden for arrays. * * @var array */ protected $hidden = [ 'password', 'remember_token', ]; }
На этом работа с базой, миграциями и моделями закончена. Переходим к контроллеру авторизации.
Контроллер авторизации для админов
Контроллер авторизации для админов мы поместим в app\Http\Controllers\AuthAdmin (AuthAdmin нужно создать) и назовем его LoginController.
php artisan make:controller AuthAdmin\LoginController
И в этот контроллер добавляем следующий код:
<?php namespace App\Http\Controllers\AuthAdmin; use Illuminate\Http\Request; use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\AuthenticatesUsers; use Auth; class LoginController extends Controller { use AuthenticatesUsers; protected $redirectTo = '/admin'; protected $redirectAfterLogout = '/admin'; public function __construct() { $this->middleware('guest', ['except' => 'logout']); } public function showLoginForm() { return view('admin.auth.login'); } protected function guard() { return Auth::guard('admin'); } }
Middleware и контроллер админ панели
По поводу контролера админ панели заморачиваться не будем: если пользователь прошел авторизацию и он является администратором, то доступ к админ панели открыт. Контроллер назовем AdminController и поместим его в app\Http\Controllers. Контроллер будет иметь два метода __construct и index. Создадим контроллер AdminController:
php artisan make:controller AdminController
И добавим в него следующий код
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Auth; class AdminController extends Controller { /** * Create a new controller instance. * * @return void */ public function __construct() { $this->middleware('isAdmin'); } /** * Show the application dashboard. * * @return \Illuminate\Http\Response */ public function index() { dd( Auth::guard('admin')->user()); } }
Метод index толком ничего не делает, если пользователь авторизован, то выводит его данные. Обратите внимание, что в Auth мы использовали guard(‘admin’). Guard с названием admin мы опишем чуть позже. Забегая вперед данный gurard будет указывать на работу с моделью Admin.
Теперь нам нужно создать middleware, который будет проверять авторизован ли пользователь и является ли администратором.
php artisan make:middleware IsAdmin
И поместим в него следующий код
<?php namespace App\Http\Middleware; use Closure; use Auth; class IsAdmin { public function handle($request, Closure $next,$guard = 'admin') { if (!Auth::guard($guard)->check()) { return redirect('/'); } return $next($request); } }
Теперь необходимо зарегистрировать данный middleware. Для этого открываем app\Http\Kernel.php и вставляем следующий код.
protected $routeMiddleware = [ … 'isAdmin' => \App\Http\Middleware\IsAdmin::class, … ]
Регистрация guard
Открываем config\auth.php и добавляем следующий код
… 'guards' => [ … 'admin' =>[ 'driver' => 'session', 'provider' => 'admin', ], … ], … 'providers' => [ … 'admin' => [ 'driver' => 'eloquent', 'model' => App\Admin::class, ], … ] …
Настройка роутов
Первое добавим стандартные роуты для авторизации, используя команду
php artisan make:auth
Отлично давайте глянем какие роуты у нас есть, для этого воспользуемся командой
php artisan route:list
Вот вывод команды:
Я выделил роуты, которые относятся к авторизации, регистрации, выходу и восстановлению пароля. Теперь давайте добавим необходимые роты для авторизации и выхода из админки. Открываем файл routes\web.php
И добавляем следующие роуты:
… Route::get('/admin','AdminController@index'); Route::get('/admin/login',['as' => 'admin.login','uses' => 'AuthAdmin\LoginController@showLoginForm']); Route::post('/admin/login',['uses' => 'AuthAdmin\LoginController@login']); Route::get('/admin/logout',['as' => 'admin.logout','uses' => 'AuthAdmin\LoginController@logout']); …
Отлично. И завершающий этап, нам необходимо создать вьюшку для отображения формы авторизации (для ввода логина и пароля)
View для отображения формы ввода логина и пароля
Если мы вернемся к нашему контроллеру, отвечающему за авторизацию для администраторов LoginController, то увидим метод showLoginForm, который возвращает вьюшку admin\auth\login. Нам необходимо в resources\views создать admin. В admin создать auth. И уже в auth создать login.blade.php и поместить в него следующий код:
@extends('layouts.app') @section('content') <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <div class="panel panel-default"> <div class="panel-heading">Вход в админ панель </div> <div class="panel-body"> <form class="form-horizontal" role="form" method="POST" action="{{ url('/admin/login') }}"> {{ csrf_field() }} <div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}"> <label for="email" class="col-md-4 control-label">E-Mail Address</label> <div class="col-md-6"> <input id="email" type="email" class="form-control" name="email" value="{{ old('email') }}" required autofocus> @if ($errors->has('email')) <span class="help-block"> <strong>{{ $errors->first('email') }}</strong> </span> @endif </div> </div> <div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}"> <label for="password" class="col-md-4 control-label">Password</label> <div class="col-md-6"> <input id="password" type="password" class="form-control" name="password" required> @if ($errors->has('password')) <span class="help-block"> <strong>{{ $errors->first('password') }}</strong> </span> @endif </div> </div> <div class="form-group"> <div class="col-md-6 col-md-offset-4"> <div class="checkbox"> <label> <input type="checkbox" name="remember"> Remember Me </label> </div> </div> </div> <div class="form-group"> <div class="col-md-8 col-md-offset-4"> <button type="submit" class="btn btn-primary"> Login </button> </div> </div> </form> </div> </div> </div> </div> </div> @endsection
Ну вот и все.
Проверяем
Вы помните, что пользователей у нас нет. Пока нет. Переходим в корень нашего сайта:
Отлично все работает, проверим формы авторизации и регистрации. Работает. Теперь попробуем перейти в /home (по идее не должно пустить, так как мы не авторизовались). Отлично, перебросило на страницу авторизации.
Теперь проверим админку. Переходим в /admin (по идее перебросит на главную, так как не авторизировались). Ок, отработала. И проверим форму авторизации для админки /admin/login
Отлично, работает
Теперь давайте создадим пользователя (пройдем регистрацию), перейдем /register и введем данные. Я ввел Name: test, E-Mail Address: test@mail.loc, Password: 123456.
Регистрацию прошли и мы сразу прошли авторизацию
Выйдем. И попробуем опять пройти авторизацию (с веденными данными). Ок, все хорошо. Давайте попробуем войти в админку (мы сейчас авторизованы как пользователь). Переходим /admin. И нас перекидывает на главную. То, что надо ведь наш пользователь не имеет права входа в админ панель. Теперь не большой «финт ушами». Открываем таблицу users и копируем полностью все данные нашего пользователя в таблицу admins (в частности нас волнует только поле password) и удаляем его из таблицы users.
Теперь наш test имеет доступ к админ панели, но не имеет доступ к /home
Давайте проверим, попробуем пройти авторизацию в кабинет, переходим /login
Не пускает.
Попробуем пройти авторизацию в админку /admin/login
Отлично мы видим данные пользователя. Ну и попытаемся выйти в кабинет /home
Нас редиректит на форму авторизации. (наш пользователь – администратор, имеет доступ к админке, но не имеет доступ к /home)
Ну вот и все. Мы с Вами разделили пользователей и админов по разным таблицам и реализовали авторизацию для них в Laravel.
Не забываем подписаться, чтобы не пропустить выхода новых статей: VK , Facebook, Twitter
Все классно работает, но мне захотелось поменять путь к админке на adminol вместо admin. Во всех созданных по этому уроку файлах проверил и заменил пути, редиректы. Но при авторизации в форме админки с правильными или неправильным логином и паролем (все равно) идет перенаправление на несущ. страницу /admin/login. Подскажите, пожалуйста, где ещё надо исправить путь?
Спасибо за ответ, я сам разобрался.
Через Policies не пробовали?
При использовании модели Admin не получается применять права доступа. Фасад Gate не видит пользователя из таблицы admins, а видит только из таблицы users модели User. Подскажите, что надо изменить, чтобы авторизация работала с моделью Admin.
Пробовал и через Policies, все равно не получается. Не видит аутентифицированного пользователя.
иди в config\auth.php и поменяй дефолтное значение
‘defaults’ => [
‘guard’ => ‘admin’,
‘passwords’ => ‘admin’,
],
Not work! Laravel 5.8
А что пишет, какая ошибка?
На 5.8.11 работает!!!