Laravel 5.6 多用户表登陆 auth user admin
Laravel 5.6 中文文档
http://laravelacademy.org/laravel-docs-5_6
http://laravelacademy.org/post/8900.html
http://laravelacademy.org/post/8851.html
注:想要快速上手?只需要在新安装的 Laravel 应用下运行 php artisan make:auth 和 php artisan migrate,这两个命令会生成用户登录注册所需要的所有东西,然后在浏览器中访问 http://your-app.dev/register 即可。
php artisan make:auth
php artisan migrate
创建用户模块 以及数据库
友情提示:新建的用于登录认证的模型类需要继承 Illuminate\Foundation\Auth\User 基类,不然后面就会出现不能认证的窘况。
use Illuminate\Foundation\Auth\User;
php artisan make:model Admin -m
模型Admin.php(参考app\User.php)
编辑app\Admin.php
use Illuminate\Foundation\Auth\User;
class Admin extends Authenticatable
{
//
use Notifiable;
protected $table = "admins";
protected $fillable = [
'name', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
}
配置下迁移文件(参照create_user_table.php)
编辑database/migrations下create_admin_table.php
/**
* 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',60);
$table->rememberToken();
$table->timestamps();
});
}
建立Admin模型对应的数据填充文件(因为管理员用户往往无法注册,所以加入的方式就是使用数据填充)
建立填充文件
php artisan make:seeder AdminsTableSeeder
配置填充文件(账号:admin@foxmail.com 密码:pass)
编辑database/seeds/AdminTableSeeder.php
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
//
factory(App\Admin::class)->create([
'name' => 'admin',
'email' => 'admin@foxmail.com',
'password' => bcrypt('pass'),
]);
}
执行填充
php artisan db:seed --class=AdminsTableSeeder
登陆mysql检查数据。
访问指定 Guard 实例
你可以使用 Auth 门面的 guard 方法指定想要使用的 guard 实例,这种机制允许你在同一个应用中对不同的认证模型或用户表实现完全独立的用户认证。
该功能可用于为不同表的不同类型用户(同一个表不同类型用户理论上也可以)实现隔离式登录提供了方便,我们只要为每张表配置一个独立的 guard 就可以了。比如我们除了 users 表之外还有一张 admins 表用于存放后台管理员,要实现管理员的单独登录,就可以这么配置 auth.php 配置文件:
编辑config/auth.php,配置好新Guard和Provider
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
]
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Admin::class,
],
],
创建后台(按照路由,控制器,中间件,视图顺序)
路由
编辑routes/web.php(路由参照vendor\laravel\framework\src\Illuminate\Routing目录下的Router.php中的auth()函数)
Route::group(['prefix' => 'admin'], function () {
Route::get('login', 'Admin\LoginController@showLoginForm');
Route::post('login', 'Admin\LoginController@login');
Route::post('logout', 'Admin\LoginController@logout');
Route::get('/', 'Admin\IndexController@index');
});
控制器
1.新建一个登陆控制器,并重写showLoginForm方法,去返回管理员的登陆页面
编辑app\Http\Controller\Admin\LoginController.php
public function showLoginForm()
{
return view('admin.login');
}
重载guard()方法,不能使用默认的返回web。这个管理员用户的验证使用的是刚刚配置好的Guard:admin
protected function guard()
{
return Auth::guard('admin');
}
重写redirectTo方法,使得登陆成功后重定向到管理员页面
/**
redirect users after lgin
*/
public function redirectTo()
{
return 'admin/';
}
要对Admin\LoginController.php加入中间件来过滤请求,当管理员已经登陆时,就要让其跳转到admin/管理页面
2.编辑app\Http\Controller\Admin\IndexController.php
/**
* 验证通过后,返回管理页面视图
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function index()
{
return view('admin/index');
}
中间件(管理页面控制器,需要中间件过滤掉没有登陆为管理员的请求)
分两步
1.没有登陆
(使用guest中间件,确认重定向到前后台登陆控制器,admin就会作为中间件参数,赋值给$guard然后调用guard获取guard:admin来验证然后不为null,就会重定向到admin/index了)
编辑guest中间件,app\Http\Middleware\RedirectIfAuthenticated.php
(详见app\Http\Kernel.php中的protected $routeMiddleware)
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
$url = $guard ? 'admin/' : '/home';
return redirect($url);
}
return $next($request);
}
然后在Admin\LoginController.php构造函数中加入此中间件
(这个guest后面的admin就会作为中间件参数)
public function __construct()
{
$this->middleware('guest:admin')->except('logout');
}
2.已经登陆
(使用admin中间件,判断是不是管理员,不是就跳到管理员登陆页面,同样使用中间件参数把admin传进来)
编辑admin中间件,app\Http\Middleware\AuthAdmin.php
(详见app\Http\Kernel.php中的protected $routeMiddleware)
public function handle($request, Closure $next, $guard)
{
if(!Auth::guard($guard)->check())
{
return redirect('admin/login');
}
return $next($request);
}
注册中间件才能使用,注册到Kernel.php中
编辑app\Http\Kernel.php
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array
*/
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'authadmin' => \App\Http\Middleware\AuthAdmin::class,
];
然后在Admin\IndexController.php构造函数中使用此中间件。
public function __construct()
{
$this->middleware('authadmin:admin');
}
把admin参数传进去。
视图
所有视图的源码我都贴在下面(都是使用user的来修改的)我的视图都放在views/admin里目录结构如图
resources/views/layouts/app.blade.php复制到resources/views/adminlayouts/app.blade.php
resources/views/auth/login.blade.php复制到resources/views/admin/login.blade.php
resources/views/home.blade.php复制到resources/views/admin/index.blade.php
编辑resources/views/adminlayouts/app.blade.php
<!DOCTYPE html>
<html lang="{{ app()->getLocale() }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</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=Raleway:300,400,600" 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('/') }}">
{{ config('app.name', 'Laravel') }}
</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">
</ul>
<!-- Right Side Of Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Authentication Links -->
@guest
<li><a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a></li>
<li><a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a></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()->name }} <span class="caret"></span>
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="{{ route('logout') }}"
onclick="event.preventDefault();
document.getElementById('logout-form').submit();">
{{ __('Logout') }}
</a>
<form id="logout-form" action="{{ route('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>
编辑resources/views/admin/login.blade.php
@extends('adminlayouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Login') }}</div>
<div class="card-body">
<form method="POST" action="{{ url('admin/login') }}">
@csrf
<div class="form-group row">
<label for="email" class="col-sm-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 autofocus>
@if ($errors->has('email'))
<span class="invalid-feedback">
<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">
<strong>{{ $errors->first('password') }}</strong>
</span>
@endif
</div>
</div>
<div class="form-group row">
<div class="col-md-6 offset-md-4">
<div class="checkbox">
<label>
<input type="checkbox" name="remember" {{ old('remember') ? 'checked' : '' }}> {{ __('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>
<a class="btn btn-link" href="{{ route('password.request') }}">
{{ __('Forgot Your Password?') }}
</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
编辑resources/views/admin/index.blade.php
@extends('adminlayouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">Dashboard</div>
<div class="card-body">
{{--@if (session('status'))--}}
{{-- <div class="alert alert-success">--}}
{{-- {{ session('status') }}--}}
{{-- </div>--}}
{{-- @endif--}}
You are logged in!{{Auth::guard('admin')->user()}}
</div>
</div>
</div>
</div>
</div>
@endsection
处理注销
经过上面的步骤,已经实现了前后台分离登录,但是不管是在前台注销,还是在后台注销,都销毁了所有的 session,导致前后台注销连在一起。所以我们还要对注销的方法处理一下。
原来的 logout 方法是这样写的,在 Illuminate\Foundation\Auth\AuthenticatesUsers 里
public function logout(Request $request)
{
$this->guard()->logout();
$request->session()->flush();
$request->session()->regenerate();
return redirect('/');
}
注意这一句
$request->session()->flush();
将所有的 session 全部清除,这里不分前台、后台,所以要对这里进行改造。
因为前台、后台注销都要修改,所以我们新建一个 trait,前后台都可以使用。
新建一个文件app/Exceptions/AuthenticatesLogout.php
<?php
namespace App\Exceptions;
use Illuminate\Http\Request;
trait AuthenticatesLogout
{
public function logout(Request $request)
{
$this->guard()->logout();
$request->session()->forget($this->guard()->getName());
$request->session()->regenerate();
return redirect('/');
}
}
我们将上面的那一句改成
$request->session()->forget($this->guard()->getName());
只是删除掉当前 guard 所创建的 session,这样就达到了分别注销的目的。
修改 Auth/LoginController.php 和 Admin/LoginController.php,将
class LoginController extends Controller
{
use AuthenticatesUsers;
改掉,在文件的前面别忘了加上 use 语句
use App\Exceptions\AuthenticatesLogout;
...
class LoginController extends Controller
{
use AuthenticatesUsers, AuthenticatesLogout {
AuthenticatesLogout::logout insteadof AuthenticatesUsers;
}
...
到这里,就完成了整个不同用户表登录认证的过程。
参考:
https://blog.csdn.net/u011580175/article/details/78231904
https://blog.csdn.net/realghost/article/details/52512268
原文链接:https://blog.csdn.net/greatyoulv/article/details/80261656
博主写的不错,刚好对中间件不太会,看了你的这篇文章理解深入多了,感谢