Laravel学习记录--基于多表用户登录认证(前/后)台

Laravel支持基于多表的用户认证,同时允许不同的数据表用户(前/后台)进行登录验证
在上一篇记录,我们完成了前台用户的认证,在这里只做后台用户登录认证
1.创建后台用户模型,并生成表
php artisan make:model Admin -m
编辑迁移文件设置表结构
在这里插入图片描述
2.编辑Admin模型
将User模型的代码复制到Admin模型

<?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',
    ];
}


3.编辑认证配置文件
要实现多表用户认证,首先要配置认证配置文件auth.php

<?php

return [

    //默认用户认证配置,即不指定特定认证服务方的话,使用以下默认配置

    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],

   //在这里配置不同的认证服务方,默认支持web和api认证
   //即web路由的请求认证和api路由的请求认证
   //如果要配置其他的认证服务方,如后台登录,需要在这里配置
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'token',
            'provider' => 'users',
        ],
    ],

   //在这里配置系统支持的认证提供者(用户数据来源)
   //默认基于User模型的EloquentProvider
   //如果系统支持不同表用户登录,需要在这里额外配置

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],

        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

   //密码重置表,默认支持user表的密码重置,对应的数据表是password_resets
   //如果要支持其他用户表的密码重置,需要在这里额外配置
    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
        ],
    ],

];

根据上面的配置项完成auth的配置,我们默认使用的webguard实现前台登录,要实现后台登录我们需要在guards数组中添加一个adminguard,参照’web’
如:

'guards'=>[
    'web'=>[
         'driver'=>'session',
         'provider'=>'users',
     ],
     'admin'=>[
         'driver'=>'session',
         'provider'=>'admins'
     ]
     'api'=>[
          'driver'=>'token',
          'provider'=>'users',
      ],
],

在providers中新增一个后台用户数据库提供者admins

'providers'=> [
    'users'=>[
         'driver'=>'eloquent',
         'model'=>App\User::class,
     ],
     'admins'=>[
         'driver'=>'eloquent',
         'model'=>App\Admin::class,
     ],
],

密码重置表在这里由于是后台用户暂不设置
完整的auth.php

<?php

return [

    //默认用户认证配置,即不指定特定认证服务方的话,使用以下默认配置

    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],

   //在这里配置不同的认证服务方,默认支持web和api认证
   //即web路由的请求认证和api路由的请求认证
   //如果要配置其他的认证服务方,如后台登录,需要在这里配置
   'guards'=>[

    'web'=>[
         'driver'=>'session',
         'provider'=>'users',
    ],
    'admin'=>[
         'driver'=>'session',
         'provider'=>'admins'
    ],
     'api'=>[
          'driver'=>'token',
          'provider'=>'users',
        ],
    ],

   //在这里配置系统支持的认证提供者(用户数据来源)
   //默认基于User模型的EloquentProvider
   //如果系统支持不同表用户登录,需要在这里额外配置

    'providers'=> [
        'users'=>[
             'driver'=>'eloquent',
             'model'=>App\User::class,
         ],
         'admins'=>[
             'driver'=>'eloquent',
             'model'=>App\Admin::class,
          ],


        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

   //密码重置表,默认支持user表的密码重置,对应的数据表是password_resets
   //如果要支持其他用户表的密码重置,需要在这里额外配置
    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
        ],
    ],

];

4.定义后台用户认证路由及控制器
4.1增加如下路由

//后台用户登录

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');
//后台管理界面

4.2创建后台认证控制器
php artisan make:controller Admin/LoginController
php artisan make:controller Admin/RegisterController
php artisan make:controller AdminController
4.3编辑Admin/LoginController.php

<?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');
    }
   //退出后跳转后台登录页面
     public function logout(Request $request)
    {
        $this->guard()->logout();

        $request->session()->invalidate();

        return redirect('admin/login');
    }
}

说明:在LoginController中我们重写了AuthenticatesUsers中的两个方法,showlLoginForm()用于显示用户后台登录界面,guuard方法用于在Auth::guard方法中传入对应的认证服务方配置并将其返回,这样使用后台登录时,使用的就是上面配置的后台认证guard了,该参数默认值是web(在auth.phpdefaults)中配置,所以我们在前台用户认证时不需要手动传入。

由于我们在中间件guest中也传入了admin参数,表示判断是否为后台登录,所以我们还要修改guest中间件对应类RedirectIfAuthenticated的处理办法—handle,当传入guardadmin时,跳转后台主页

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);
    }

同时我们还要编辑后台用户注册类Admin\RegisterController.php

<?php

namespace App\Http\Controllers\Admin;

use App\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;

class RegisterController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Register Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles the registration of new users as well as their
    | validation and creation. By default this controller uses a trait to
    | provide this functionality without requiring any additional code.
    |
    */

    use RegistersUsers;

    /**
     * Where to redirect users after registration.
     *
     * @var string
     */
    protected $redirectTo = '/admin';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    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:users',
            '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' => bcrypt($data['password']),
        ]);
    }
}

4.4编辑AdminController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class AdminController extends Controller
{
    //
    public function __construct()
    {
    	$this->middleware('auth:admin');
    }
    public function index(){
    	return view('admin.home');
    }

}

通过index方法渲染登录后的管理页面,如果没有登录,访问该方法会通过auth中间件进行处理,我们在中间件中也传入了admin参数,用于判断后台是否登录,同样我们还要修改auth中间件对应类Authenticate来处理后台未登录的跳转 如果没有需要我们手动创建

<?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);
            }
        }

        // 这里我们以 guards 传入的第一个参数为准选择跳转到的登录页面
        $guard = $guards[0];
        if ($guard == 'admin') {
            $this->redirectTo = route('admin.login');
        }

        throw new AuthenticationException(
            'Unauthenticated.', $guards, $this->redirectTo ? : $this->redirectTo($request)
        );
    }
}

5.视图文件创建及修改
5.1创建后台视图,创建后台视图文件之前我们需要先为后台认证创建一个布局文件
复制layouts\app.blade.php进行编写
创建admin.blade.php布局文件

<!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>

5.2创建后台认证视图
创建后台认证视图,先在rescources/views目录下创建admin子目录,然后将前台用户认证模板复制并修改即可
login页面

@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">Login</div>

                <div class="panel-body">
                    <form class="form-horizontal" method="POST" action="{{ route('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="text" class="form-control" name="name" 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" {{ old('remember') ? 'checked' : '' }}> 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>

                                <a class="btn btn-link" href="{{ route('password.request') }}">
                                    Forgot Your Password?
                                </a>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

register页面

@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_field()}}

                        <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

home页面

@extends('layouts.app')

@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

                    欢迎登录管理员
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

登录效果(管理员)
在这里插入图片描述
登录效果(普通用户)
在这里插入图片描述

发布了44 篇原创文章 · 获赞 1 · 访问量 1565

猜你喜欢

转载自blog.csdn.net/weixin_45143481/article/details/104145954