Implementation of user authentication function based on multiple tables (front and rear users)


Larave supports user authentication based on multiple tables, that is, users of different data tables (such as foreground users and background users) are allowed to log in and authenticate at the same time. Let's take the previous background user login authentication as an example to briefly introduce the user registration and login functions based on different data tables.

1. Generate certified scaffold

About this, we have Quickly realize user authentication through built-in scaffolding This tutorial discussed it in detail. If you don't understand it, you can check the corresponding content. If you have already seen it, please skip this step.

2. Realize frontend user login

We use the frame users Table stores foreground users. Next, we will implement the registration and login of foreground users. Pass previously run make:auth Command, we have generated all the codes and data tables required for foreground authentication, and we Previous Tutorial Demonstrated in users The table stores the registration and login process of users.

3. Create background user model

We focus on the background user login. Suppose our background user table is admins , the corresponding model class is Admin First, use the following Artisan command to generate the background user model and the corresponding database migration file:

 php artisan make:model Admin -m

Edit the newly generated database migration file create_admins_table Corresponding to migration class up The method code is as follows (directly from users Copy from table migration):

 public function up() { Schema::create('admins', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); }); }

Then run the migration command to create the table in the database:

 php artisan migrate

Then update Admin The model classes are as follows:

 <? php namespace App; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; class Admin extends Authenticatable { use Notifiable; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'name', 'email', 'password', ]; /** * The attributes excluded from the model's JSON form. * * @var array */ protected $hidden = [ 'password', 'remember_token', ]; }

4. Edit Authentication Profile

To implement multi table user authentication, first configure the authentication profile auth.php Here we implement the function of front and background user login, so the corresponding configuration is as follows. The default user authentication related configuration of this configuration file is as follows:

 //The default user authentication configuration, that is, if no specific authentication server is specified, the following default configuration is used 'defaults' => [ 'guard' => 'web', 'passwords' => 'users', ], //Configure different authentication service providers here, and support web and api authentication by default, //Namely, request authentication of web routing and request authentication of api routing //If you want to configure other authentication service providers, such as background login, you need to configure them here 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'token', 'provider' => 'users', ], ], //Configure the authentication provider (user data source) supported by the system here, //The default is EloquentProvider based on the User model, //If the system supports different forms of user login, additional configuration is required here 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\User::class, ], // 'users' => [ //     'driver' => 'database', //     'table' => 'users', // ], ], //Password reset table, which supports password reset of users table by default, and the corresponding data table is password_resets //If you want to support password reset of other user tables, you need to configure additional settings here 'passwords' => [ 'users' => [ 'provider' => 'users', 'table' => 'password_resets', 'expire' => 60, ], ],

In the comments, I pointed out the role of each configuration item and how to configure multi table user authentication. We still use the default web Guard realizes front desk login, and then adds a new admin Guard is used for background login, and then providers Add a background user data provider in admins The background users are all our own, so we don't need to do password reset. If you are facing more complex user systems, such as e-commerce systems, involving buyers, sellers, and system background users, you may need to set password reset tables for different user tables passwords Reference in configuration item users Just set the table, and then create the corresponding data table. The following is the updated auth.php Configuration table:

 <? php return [ 'defaults' => [ 'guard' => 'web', 'passwords' => 'users', ], 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'admin' => [ 'driver' => 'session', 'provider' => 'admins', ], 'api' => [ 'driver' => 'token', 'provider' => 'users', ], ], 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\User::class, ], 'admins' => [ 'driver' => 'eloquent', 'model' => App\Admin::class, ], ], 'passwords' => [ 'users' => [ 'provider' => 'users', 'table' => 'password_resets', 'expire' => 60, ], ], ];

The authentication configuration is configured by guard and provider Two parts, guard It is used to configure the authentication request server, such as foreground login, background login, API login, and whether it is based on Web routing or API routing (Web routing is authenticated based on Session, and API routing is authenticated based on Token); provider It is used to configure the user authentication data provider, whether to pass Eloquent or database, and which data table. Therefore, we added two new configuration items admin and admins Configuration item that identifies the background login based on Web routing, and Admin Model classes provide data support.

5. Define background user authentication route and controller

Background authentication route

After making the above preparations, we will officially start to implement background authentication. First, define the background user authentication route. In the routes/web.php The following routing definitions are added to:

 Route::get('admin/login', 'Admin\ LoginController@showLoginForm ')->name('admin.login'); Route::post('admin/login', 'Admin\ LoginController@login '); Route::get('admin/register', 'Admin\ RegisterController@showRegistrationForm ')->name('admin.register'); Route::post('admin/register', 'Admin\ RegisterController@register '); Route::post('admin/logout', 'Admin\ LoginController@logout ')->name('admin.logout'); Route::get('admin', ' AdminController@index ')->name('admin.home');

Background authentication controller

Then use the Artisan command to create the corresponding controller:

 php artisan make:controller Admin/LoginController php artisan make:controller Admin/RegisterController php artisan make:controller AdminController

edit Admin/LoginController.php The codes are as follows:

 <? php namespace App\Http\Controllers\Admin; use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Http\Request; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Auth; class LoginController extends Controller { use AuthenticatesUsers; protected $redirectTo = '/admin'; public function __construct() { $this->middleware('guest:admin')->except('logout'); } public function showLoginForm() { return view('admin.login'); } protected function guard() { return Auth::guard('admin'); } //Jump to the page after exiting protected function loggedOut(Request $request) { return redirect(route('admin.login')); } }

We can see that we have rewritten AuthenticatesUsers Two methods in, showLoginForm() Method The user displays the background login form, guard() Method is used in the Auth::guard In the method, the corresponding authentication server configuration is passed in and returned. In this way, the background authentication guard configured in the previous step is used for background login. The default value of this parameter is web (on auth.php Of defaults So we do not need to manually pass in the foreground user authentication.

In addition, we use middleware guest It also came in admin Parameter to determine whether the background is logged in. To this end, we need to modify guest Middleware corresponding class RedirectIfAuthenticated Treatment method of handle , when incoming guard yes admin To jump to the background home page:

 public function handle($request,  Closure $next, $guard = null) { if (Auth::guard($guard)->check()) { if ($guard == 'admin') { return redirect('/admin'); } return redirect('/home'); } return $next($request); }

Finally, we also set the jump path after login to /admin And override loggedOut Method Return to the background login page after exiting the background.

Similarly, edit Admin/RegisterController.php The codes are as follows:

 <? php namespace App\Http\Controllers\Admin; use App\Admin; use Illuminate\Foundation\Auth\RegistersUsers; use Illuminate\Http\Request; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; class RegisterController extends Controller { use RegistersUsers; protected $redirectTo = '/admin'; public function __construct() { $this->middleware('guest:admin'); } public function showRegistrationForm() { return view('admin.register'); } protected function guard() { return Auth::guard('admin'); } /** * Get a validator for an incoming registration request. * * @param  array  $data * @return \Illuminate\Contracts\Validation\Validator */ protected function validator(array $data) { return Validator::make($data, [ 'name' => 'required|string|max:255', 'email' => 'required|string|email|max:255|unique:admins', 'password' => 'required|string|min:6|confirmed', ]); } /** * Create a new user instance after a valid registration. * * @param  array  $data * @return \App\User */ protected function create(array $data) { return Admin::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => Hash::make($data['password']), ]); } }

The corresponding logic is similar to login, so I won't say much about it.

Then edit AdminController.php The codes are as follows:

 <? php namespace App\Http\Controllers; use Illuminate\Http\Request; class AdminController extends Controller { /** * Create a new controller instance. * * @return void */ public function __construct() { $this->middleware('auth:admin'); } /** * Show the application dashboard. * * @return \Illuminate\Http\Response */ public function index() { return view('admin.home'); } }

adopt index Method to render the background login page. If you do not log in to access this method, you will auth Middleware for processing. We also import admin Parameter, which is used to determine whether the background is logged in. Similarly, we also need to modify auth Middleware corresponding class Authenticate To handle the background logout jump, this time we rewrite the parent class's authenticate Method to achieve:

 <? php namespace App\Http\Middleware; use Illuminate\Auth\AuthenticationException; use Illuminate\Auth\Middleware\Authenticate as Middleware; class Authenticate extends Middleware { protected $redirectTo = ''; /** * Get the path the user should be redirected to when they are not authenticated. * * @param  \Illuminate\Http\Request  $request * @return string */ protected function redirectTo($request) { return route('login'); } protected function authenticate($request, array $guards) { if (empty($guards)) { $guards = [null]; } foreach ($guards as $guard) { if ($this->auth->guard($guard)->check()) { return $this->auth->shouldUse($guard); } } //Here we select the login page to jump to based on the first parameter passed in by guards $guard = $guards[0]; if ($guard == 'admin') { $this->redirectTo = route('admin.login'); } throw new AuthenticationException( 'Unauthenticated.', $ guards, $this->redirectTo ? : $this->redirectTo($request) ); } }

6. View file creation and modification

Create a background layout file

Before creating the background authentication view, first create a layout file for the background authentication. Let's copy it layouts/app.blade.php Write

 cp resources/views/layouts/app.blade.php resources/views/layouts/admin.blade.php

Then modify admin.blade.php The layout file code is as follows:

 <! DOCTYPE html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!--  CSRF Token --> <meta name="csrf-token" content="{{ csrf_token() }}"> <title>{{ config('app.name', 'Laravel') }} Admin</title> <!--  Scripts --> <script src="{{ asset('js/app.js') }}" defer></script> <!--  Fonts --> <link rel="dns-prefetch" href=" https://fonts.gstatic.com "> <link href=" https://fonts.googleapis.com/css?family=Nunito " rel="stylesheet" type="text/css"> <!--  Styles --> <link href="{{ asset('css/app.css') }}" rel="stylesheet"> </head> <body> <div id="app"> <nav class="navbar navbar-expand-md navbar-light navbar-laravel"> <div class="container"> <a class="navbar-brand" href="{{ url('/admin') }}"> {{ config('app.name', 'Laravel') }} Admin </a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <!--  Left Side Of Navbar --> <ul class="navbar-nav mr-auto"> <li class="nav-item"> <a class="nav-link" href="{{ url('/') }}">Home</a> </li> </ul> <!--  Right Side Of Navbar --> <ul class="navbar-nav ml-auto"> <!--  Authentication Links --> @guest <li class="nav-item"> <a class="nav-link" href="{{ route('admin.login') }}">{{ __('Login') }}</a> </li> <li class="nav-item"> @if (Route::has('admin.register')) <a class="nav-link" href="{{ route('admin.register') }}">{{ __('Register') }}</a> @endif </li> @else <li class="nav-item dropdown"> <a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre> {{ Auth::user('admin')->name }} <span class="caret"></span> </a> <div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown"> <a class="dropdown-item" href="{{ route('admin.logout') }}" onclick="event.preventDefault(); document.getElementById('logout-form').submit(); "> {{ __('Logout') }} </a> <form id="logout-form" action="{{ route('admin.logout') }}" method="POST" style="display: none;"> @csrf </form> </div> </li> @endguest </ul> </div> </div> </nav> <main class="py-4"> @yield('content') </main> </div> </body> </html>

We can see that we have replaced all the registration, login and exit links with those related to background authentication, modified the navigation bar, added a "Home" link to jump to the application home page, and passed the Auth::user('admin')->name Get the background login user name. The logic here is the same as the previous background authentication controller Auth::user() In the method, the specified user authentication service party is passed in to obtain the corresponding user authentication information. The default value is web Therefore, we do not need to manually pass in this parameter value in the foreground user login process.

Create background authentication view

Finally, we create the background user authentication corresponding view file resources/views Create under directory admin Subdirectory, and then copy the foreground user authentication view template and make slight modifications:

 cp resources/views/auth/login.blade.php resources/views/admin/ cp resources/views/auth/register.blade.php resources/views/admin/ cp resources/views/home.blade.php resources/views/admin/

modify admin/login.blade.php The codes are as follows:

 @extends('layouts.admin') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">{{ __('Admin Login') }}</div> <div class="card-body"> <form method="POST" action="{{ route('admin.login') }}"> @csrf <div class="form-group row"> <label for="email" class="col-sm-4 col-form-label text-md-right">{{ __('Email') }}</label> <div class="col-md-6"> <input id="email" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ old('email') }}" required autofocus> @if ($errors->has('email')) <span class="invalid-feedback" role="alert"> <strong>{{ $errors->first('email') }}</strong> </span> @endif </div> </div> <div class="form-group row"> <label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label> <div class="col-md-6"> <input id="password" type="password" class="form-control{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password" required> @if ($errors->has('password')) <span class="invalid-feedback" role="alert"> <strong>{{ $errors->first('password') }}</strong> </span> @endif </div> </div> <div class="form-group row"> <div class="col-md-6 offset-md-4"> <div class="form-check"> <input class="form-check-input" type="checkbox" name="remember" id="remember" {{ old('remember') ? 'checked' : '' }}> <label class="form-check-label" for="remember"> {{ __('Remember Me') }} </label> </div> </div> </div> <div class="form-group row mb-0"> <div class="col-md-8 offset-md-4"> <button type="submit" class="btn btn-primary"> {{ __('Login') }} </button> </div> </div> </form> </div> </div> </div> </div> </div> @endsection

modify admin/register.blade.php The codes are as follows:

 @extends('layouts.admin') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">{{ __('Admin Register') }}</div> <div class="card-body"> <form method="POST" action="{{ route('admin.register') }}"> @csrf <div class="form-group row"> <label for="name" class="col-md-4 col-form-label text-md-right">{{ __('Name') }}</label> <div class="col-md-6"> <input id="name" type="text" class="form-control{{ $errors->has('name') ? ' is-invalid' : '' }}" name="name" value="{{ old('name') }}" required autofocus> @if ($errors->has('name')) <span class="invalid-feedback" role="alert"> <strong>{{ $errors->first('name') }}</strong> </span> @endif </div> </div> <div class="form-group row"> <label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label> <div class="col-md-6"> <input id="email" type="email" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ old('email') }}" required> @if ($errors->has('email')) <span class="invalid-feedback" role="alert"> <strong>{{ $errors->first('email') }}</strong> </span> @endif </div> </div> <div class="form-group row"> <label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label> <div class="col-md-6"> <input id="password" type="password" class="form-control{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password" required> @if ($errors->has('password')) <span class="invalid-feedback" role="alert"> <strong>{{ $errors->first('password') }}</strong> </span> @endif </div> </div> <div class="form-group row"> <label for="password-confirm" class="col-md-4 col-form-label text-md-right">{{ __('Confirm Password') }}</label> <div class="col-md-6"> <input id="password-confirm" type="password" class="form-control" name="password_confirmation" required> </div> </div> <div class="form-group row mb-0"> <div class="col-md-6 offset-md-4"> <button type="submit" class="btn btn-primary"> {{ __('Register') }} </button> </div> </div> </form> </div> </div> </div> </div> </div> @endsection

modify admin/home.blade.php The codes are as follows:

 @extends('layouts.admin') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">Admin Dashboard</div> <div class="card-body"> @if (session('status')) <div class="alert alert-success" role="alert"> {{ session('status') }} </div> @endif You are logged in the admin dashboard! </div> </div> </div> </div> </div> @endsection

7. Background user authentication test

So far, all the functions of background user registration and login have been realized, which can be accessed in the browser http://blog.test/admin , you will jump to the background login page:

If there is no registration, click the "Register" link in the upper right corner to jump to the registration page to register:

Register a user whose user name is "Administrator". After successful registration, the page will jump to http://blog.test/admin , indicating that the authentication is successful:

Click the hidden "Logout" link in the upper right corner to jump to the background login page. In this way, a complete background registration, login and exit function is completed.


give the thumbs-up Cancel Like Collection Cancel Collection

<<Previous: User registration and login process and implementation of multi field login

>>Next: API Request Authentication via Passport: Single Page Application