Laravel5.3 多表验证(包括登录注册,找回密码,发送邮件)

主要内容#

我们在开发过程中,往往会需要前台后台两个部分组成一个完整的项目,一些公司需要频繁的在短期内开发一个项目,往往这些项目的一部分功能是重复的,所以可以提炼出来做为模板,以供下个项目使用,之前有人发了登录部分的实现,今天想聊一下包括找回密码和发送邮件在内的一些细节,我们都通过 laravel 内置的验证来完成。

第一步#

在一个初始的 laravel 框架中,运行这个 php artisan make:auth 来生成我们需要的基础验证路由,视图和控制器,我们初始化了一个 laravel 框架之后,运行该命令增加的文件如下。

file

更改结构,复制粘贴#

我们需要将她复制为两个模块,一个是前台(以 web 命名),一个是后台(以 admin 命名)。

路由#

Route::get('/', function () {
    return view('welcome');
});

Route::group([
    'namespace' => 'Web',
], function ($route) {

    $route->get('/home', 'HomeController@index');

    Auth::routes();
});

Route::group([
    'prefix'    => 'admin',
    'namespace' => 'Admin',
], function ($route) {

    Auth::routes();

    $route->get('/', 'HomeController@index');
});

视图#

views 下新建两个文件夹,一个为 web 一个是 admin ,将生成的 auth 文件夹复制,扔在这两个目录下,原来的删掉就好,将 home.blade.php 放在 web 下,再复制一份放在 admin 下,可以更改里边内容来区别用户和管理员界面,并且一定记得修改 admin 下的 4 个表单的 actionlogin 视图的 reset password 的链接,加上前缀 admin views 修改好后如下:

file

控制器#

和视图类似,在 Controllers 目录下新建两个文件夹 WebAdmin,将 Auth 文件夹复制并扔在这两个文件夹里,删除原来的 Auth ,并把 HomeController.php 扔在 Web 目录下,并且复制一份扔在 Admin 并且修改这两个 HomeContrllerindex 方法里 view('web.home')view('admin.home') ,目录下此时注意修改命名空间,将这
10 个控制器的 namespace 根据所在目录分别加上 WebAdmin,以 Web/Auth/LoginController.php 为例,修改命名空间为 namespace App\Http\Controllers\Web\Auth; 复制粘贴的工作就做完了,此时的控制器如下:

file

可是此时打开登录界面会产生如下错误:

file

注意,我们可以看到 LoginController 里的 showLoginForm 方法,我们回到 Web/LoginController.php 可以看到她引用了一个 trait

<?php

namespace App\Http\Controllers\Admin\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

class LoginController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles authenticating users for the application and
    | redirecting them to your home screen. The controller uses a trait
    | to conveniently provide its functionality to your applications.
    |
    */

    use AuthenticatesUsers;

    ......

跟踪过去后是如下代码:

<?php

namespace Illuminate\Foundation\Auth;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Lang;

trait AuthenticatesUsers
{
    use RedirectsUsers, ThrottlesLogins;

    /**
     * Show the application's login form.
     *
     * @return \Illuminate\Http\Response
     */
    public function showLoginForm()
    {
        return view('auth.login');
    }

    ......
}

这个 trait 很重要我们之后会覆盖这里的其他方法,此时因为我们在 views 下移走了 auth 目录,所以是错到了这里,可是这个 trait 是大家公共使用的,我们不能随便在此更改,因此需要在 LoginController 里覆盖这个方法,在 LoginController 里增加如下代码:

public function showLoginForm()
{
    return view('web.auth.login');
}

这样就成功的走到了我们更改后的目录里,同理覆盖 RegisterController.php 里的 showRegistrationForm() 方法,以及对应的 Admin 目录下的控制器方法,控制器到这里先停一下,

中间件#

我们需要聊点别的。此时用户的登录注册页面可以正常打开,但是管理员的却不行,因为我们此时走的是同一个验证的中间件,所以需要一个验证身份的中间件,新建一个 middlewareAdminAuthMiddleware.php 如下:
(参考: 教程: Laravel 5.3 多用户表登录

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;

class AdminAuthMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure $next
     * @return mixed
     */
    public function handle($request, Closure $next, $guard = null)
    {
        if (Auth::guard($guard)->guest()) {
            if ($request->ajax() || $request->wantsJson()) {
                return response('Unauthorized.', 401);
            } else {
                return redirect()->guest('/admin/login');
            }
        }
        return $next($request);
    }
}

App\Http\Kernel 中的数组 $routeMiddleware 注册

/**
     * 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.admin' => \App\Http\Middleware\AdminAuthMiddleware::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    ];

修改 RedirectIfAuthenticated.php

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;

class RedirectIfAuthenticated
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string|null  $guard
     * @return mixed
     */
    public function handle($request, Closure $next, $guard = null)
    {
        if (Auth::guard($guard)->check()) {
            // 根据不同 guard 跳转到不同的页面
            $url = $guard ? 'admin/':'/';
            return redirect($url);
        }

        return $next($request);
    }
}

更改配置文件(其中涉及的模型请继续往下看):
config/auth.conf:

代码已被折叠,点此展开

模型#

app 目录下新建 Models 目录,把 User.php 复制一份改名为 Admin.php ,注意同时修改类名为 Admin , 新建数据表:

php artisan make:migration create_admins_table
php artisan make:migration create_admin_password_resets_table
php artisan make:seeder UsersTableSeeder
php artisan make:seeder AdminsTableSeeder

他们分别长这样:

代码已被折叠,点此展开

之后迁移数据库,我们的模型就完成了,接下来继续完成控制器部分。

完善控制器#

前台部分#

Web/Auth/RegisterController.php 修改移了位置的 User 模型,前端登录功能不需要更改,注册功能改这里之后就完成了。

use App\Models\User;

Web/Auth/ForgotPasswordController.php

<?php

namespace App\Http\Controllers\Web\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
use Illuminate\Support\Facades\Password;

class ForgotPasswordController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Password Reset Controller
    |--------------------------------------------------------------------------
    |
    | This controller is responsible for handling password reset emails and
    | includes a trait which assists in sending these notifications from
    | your application to your users. Feel free to explore this trait.
    |
    */

    use SendsPasswordResetEmails;

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest');
    }

    public function showLinkRequestForm()
    {
        return view('web.auth.passwords.email');
    }

    protected function guard()
    {
        return Auth::guard('web');
    }

    public function broker()
    {
        return Password::broker('users');
    }
}

Web/Auth/ResetPasswordController.php

<?php

namespace App\Http\Controllers\Web\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Password;

class ResetPasswordController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Password Reset Controller
    |--------------------------------------------------------------------------
    |
    | This controller is responsible for handling password reset requests
    | and uses a simple trait to include this behavior. You're free to
    | explore this trait and override any methods you wish to tweak.
    |
    */

    use ResetsPasswords;

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest');
    }

    public function showResetForm(Request $request, $token = null)
    {
        //这里根据需求来看是否需要把邮箱直接带到页面上
        return view('web.auth.passwords.reset')->with(
            ['token' => $token, 'email' => $request->email]
        );
    }

    public function broker()
    {
        return Password::broker('users');
    }
}

.env 里配置自己的 mailtrap https://mailtrap.io 以供发邮件测试,登录网站后去看他随机给的用户名密码贴上去,加密不贴:

MAIL_DRIVER=smtp
MAIL_HOST=mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ENCRYPTION=

测试用户端找回密码可用。前台大功告成~

后台部分#

Admin/Auth/LoginController.php

代码已被折叠,点此展开

Admin/Auth/ForgotPasswordController.php

<?php

namespace App\Http\Controllers\Admin\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
use Illuminate\Support\Facades\Password;

class ForgotPasswordController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Password Reset Controller
    |--------------------------------------------------------------------------
    |
    | This controller is responsible for handling password reset emails and
    | includes a trait which assists in sending these notifications from
    | your application to your users. Feel free to explore this trait.
    |
    */

    use SendsPasswordResetEmails;

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest');
    }

    public function showLinkRequestForm()
    {
        return view('admin.auth.passwords.email');
    }

    protected function guard()
    {
        return Auth::guard('admin');
    }

    public function broker()
    {
        return Password::broker('admins');
    }
}

邮件可以正常发送,但是邮件的内容里的链接不对啊,所以在模型 Models/Admin.php 里加入方法:

**
     * 覆盖了Authenticatable里的trait CanResetPassword的方法
     *
     * @param string $token
     */
    public function sendPasswordResetNotification($token)
    {
        $this->notify(new AdminResetPassword($token));
    }

然后新建 Notificationphp artisan make:notification AdminResetPassword
生成文件 app/Notifications/AdminResetPassword.php 修改内容如下:

代码已被折叠,点此展开

当然您也可以通过 Notification 自定义邮件视图,到此邮件可以正常发送。

Admin/Auth/ResetPasswordController.php 修改后可以正常重置密码,注册部分就不说了,一般情况后台管理员不需要注册,而且就算有业务需求,想必大家看到也能懂怎么改了。

<?php

namespace App\Http\Controllers\Admin\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Password;

class ResetPasswordController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Password Reset Controller
    |--------------------------------------------------------------------------
    |
    | This controller is responsible for handling password reset requests
    | and uses a simple trait to include this behavior. You're free to
    | explore this trait and override any methods you wish to tweak.
    |
    */

    use ResetsPasswords;

    public $redirectTo = '/admin';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest');
    }

    public function showResetForm(Request $request, $token = null)
    {
        return view('admin.auth.passwords.reset')->with(
            ['token' => $token, 'email' => $request->email]
        );
    }

    protected function guard()
    {
        return \Auth::guard('admin');
    }

    public function broker()
    {
        return Password::broker('admins');
    }
}

Admin/HomeController.php 在默认构造函数中进行权限判断,以助于在访问 /admin 的 url 的时候能正常跳转到 /admin/login

<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class HomeController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth.admin:admin');
    }

    /**
     * Show the application dashboard.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return view('admin.home');
    }
}

今天实在无聊,就写写博客啥的发泄一下。。。笔者边做边写的,理应没多大问题,其中涉及部分 laravel 的源码推荐大家可以看看,做的时候主要是 broker() 方法找不到位置,后来发现是在 app.phpproviders 数组中注册的一个 service provider Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,,不懂得可以留言,有遗漏的地方可以留言,笔者定会及时改正~

项目地址 https://github.com/horan-geeker/laravel5.3...

本帖已被设为精华帖!
本帖由系统于 7年前 自动加精
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。