laravel 5.2 用户注册和登录

laravel5.2 验证有所改动,增加了一个叫guard的东西,这个东西主要是负责检查用户的session之类的

原文有提到:https://laravel.com/docs/5.2/authentication#introduction

At its core, Laravel's authentication facilities are made up of "guards" and "providers". Guards define how users are authenticated for each request. For example, Laravel ships with a session guard which maintains state using session storage and cookies and a token guard, which authenticates users using a "API token" that is passed with each request.

这个命令会自动创建一些验证相关的文件resources/views/auth 和resources/views/layouts,不过我们暂时先不用,先理解过程。

php artisan make:auth

先提前布置一下路由表

app/Http/routes.php

Route::group(['middleware' => ['web']], function () {
    Route::resource('/articles','ArticlesController');

    Route::get('auth/login','Auth\AuthController@getLogin'); //打开登录页面,用get
    Route::post('auth/login','Auth\AuthController@postLogin'); //提交request给login页面的postLogin方法,其实是给Auth\AuthController的postLogin

    Route::get('auth/register','Auth\AuthController@getRegister'); //类似
    Route::post('auth/register','Auth\AuthController@postRegister');//类似

    Route::get('auth/logout','Auth\AuthController@getLogout'); //logout单独独立出来,也是类似的方式使用
//        Route::get('auth/logout',function(){
//            Auth::logout();
//        });

});

需要说明一下:

  1. 上面这些在laravel 5.2里面都是要包含在web这个中间件的['middleware' => ['web'],除了csrf之外,还有一些验证的逻辑会有关联。

  2. login 和 register是在“保护”内的,而logout则不是,具体可以看AuthController.php,主要是因为logout比较随意,也不能用session来限制其访问

  3. 上面这些路由都不是默认提供的,需要自己手写,主要是因为laravel 5.2开始没有提供,不过正因为这样,整个流程也比较清晰的整理出来

  4. laravel这个默认登录注册是需要跟model关联的,如果model有问题,则也会影响整个过程,laravel把很多东西都封装好了,对于一般人来说,不容易知道里面的流程怎么生效的,需要不断研究学习源码才行。

这是我理解的过程图


首先看AuthController

app/Http/Controllers/Auth/AuthController.php

< ?php

namespace App\Http\Controllers\Auth;

use App\User;
use Validator;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;

class AuthController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Registration & Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles the registration of new users, as well as the
    | authentication of existing users. By default, this controller uses
    | a simple trait to add these behaviors. Why don't you explore it?
    |
    */

    use AuthenticatesAndRegistersUsers, ThrottlesLogins;  //使用了这2个类作为主要的验证功能类,下面会说到

    /**
     * Where to redirect users after login / registration.
     *
     * @var string
     */
    protected $redirectTo = '/';  //这个是登录成功的重定向链接,有时候需要修改。

    /**
     * Create a new authentication controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware($this->guestMiddleware(), ['except' => 'logout']);   //排除了logout,不在中间件保护范围内
    }

    /**
     * Get a validator for an incoming registration request.
     *
     * @param  array  $data
     * @return \Illuminate\Contracts\Validation\Validator
     */
    protected function validator(array $data)  //这里自带了一个验证逻辑,request的验证有2种方法,一种是写request文件,一种就是用validator
    {
        return Validator::make($data, [
            'name' => 'required|max:255',
            'email' => 'required|email|max:255|unique:users',
            'password' => 'required|min:6|confirmed',  //默认有这些验证逻辑,这个逻辑是有讲究的,因为默认的laravel验证注册登录是会关联到这里的。
        ]);
    }

    /**
     * Create a new user instance after a valid registration.
     *
     * @param  array  $data
     * @return User
     */
    protected function create(array $data)  //这个就是create,在函数体里面就是用了model的create方法,直接在数据库生成数据
    {
        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => bcrypt($data['password']),
        ]);
    }
}

然后我们看AuthenticatesAndRegistersUsers

vendor/laravel/framework/src/Illuminate/Foundation/Auth/AuthenticatesAndRegistersUsers.php

< ?php

namespace Illuminate\Foundation\Auth;

trait AuthenticatesAndRegistersUsers
{
    use AuthenticatesUsers, RegistersUsers {//这里是重点,使用了两个类,一个是验证用户,一个是注册用户
        AuthenticatesUsers::redirectPath insteadof RegistersUsers;  
        AuthenticatesUsers::getGuard insteadof RegistersUsers;
    }
}

然后我们再看AuthenticatesUsers

因为我们在路由上写了要调用getlogin,postlogin,getregister,postregister,而AuthenticatesUsers就是主要处理getlogin,postlogin的。

vendor/laravel/framework/src/Illuminate/Foundation/Auth/AuthenticatesUsers.php

<?php

namespace Illuminate\Foundation\Auth;

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

trait AuthenticatesUsers
{
    use RedirectsUsers;

    /**
     * Show the application login form.
     *
     * @return \Illuminate\Http\Response
     */
    public function getLogin()  //getLogin在此!
    {
        return $this->showLoginForm();
    }

    /**
     * Show the application login form.
     *
     * @return \Illuminate\Http\Response
     */
    public function showLoginForm()  //其实调用这个showLoginForm
    {
        $view = property_exists($this, 'loginView')
                    ? $this->loginView : 'auth.authenticate';

        if (view()->exists($view)) {
            return view($view);
        }

        return view('auth.login'); //看到这里可以看出,判断是否存在auth.authenticate文件,如果没有则用auth.login,这个文件其实就是views文件夹下面的blade文件,即resources/views/auth/login.blade.php
    }

    /**
     * Handle a login request to the application.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function postLogin(Request $request) //这里是postlogin
    {
        return $this->login($request);
    }

    /**
     * Handle a login request to the application.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function login(Request $request) //其实调用的是login
    {
        $this->validateLogin($request);

        // If the class is using the ThrottlesLogins trait, we can automatically throttle
        // the login attempts for this application. We'll key this by the username and
        // the IP address of the client making these requests into this application.
        $throttles = $this->isUsingThrottlesLoginsTrait();  //这个是判读用户登录的频率相关的

        if ($throttles && $lockedOut = $this->hasTooManyLoginAttempts($request)) {  //这里有一个更详细的toomanylogin
            $this->fireLockoutEvent($request);

            return $this->sendLockoutResponse($request);
        }

        $credentials = $this->getCredentials($request);  //这里是用来确认用户是否登陆过,会跟remember有关,就是免登陆相关的。

        if (Auth::guard($this->getGuard())->attempt($credentials, $request->has('remember'))) {
            return $this->handleUserWasAuthenticated($request, $throttles);
        }

        // If the login attempt was unsuccessful we will increment the number of attempts
        // to login and redirect the user back to the login form. Of course, when this
        // user surpasses their maximum number of attempts they will get locked out.
        if ($throttles && ! $lockedOut) {
            $this->incrementLoginAttempts($request);
        }

        return $this->sendFailedLoginResponse($request);
    }

    /**
     * Validate the user login request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return void
     */
    protected function validateLogin(Request $request)
    {
        $this->validate($request, [
            $this->loginUsername() => 'required', 'password' => 'required',
        ]);
    }

    /**
     * Send the response after the user was authenticated.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  bool  $throttles
     * @return \Illuminate\Http\Response
     */
    protected function handleUserWasAuthenticated(Request $request, $throttles)
    {
        if ($throttles) {
            $this->clearLoginAttempts($request);
        }

        if (method_exists($this, 'authenticated')) {
            return $this->authenticated($request, Auth::guard($this->getGuard())->user());
        }

        return redirect()->intended($this->redirectPath());
    }

    /**
     * Get the failed login response instance.
     *
     * @param \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    protected function sendFailedLoginResponse(Request $request)
    {
        return redirect()->back()
            ->withInput($request->only($this->loginUsername(), 'remember'))
            ->withErrors([
                $this->loginUsername() => $this->getFailedLoginMessage(),
            ]);
    }

    /**
     * Get the failed login message.
     *
     * @return string
     */
    protected function getFailedLoginMessage()
    {
        return Lang::has('auth.failed')
                ? Lang::get('auth.failed')
                : 'These credentials do not match our records.';
    }

    /**
     * Get the needed authorization credentials from the request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    protected function getCredentials(Request $request)
    {
        return $request->only($this->loginUsername(), 'password');
    }

    /**
     * Log the user out of the application.
     *
     * @return \Illuminate\Http\Response
     */
    public function getLogout()
    {
        return $this->logout();
    }

    /**
     * Log the user out of the application.
     *
     * @return \Illuminate\Http\Response
     */
    public function logout()
    {
        Auth::guard($this->getGuard())->logout();

        return redirect(property_exists($this, 'redirectAfterLogout') ? $this->redirectAfterLogout : '/');
    }

    /**
     * Get the guest middleware for the application.
     */
    public function guestMiddleware()
    {
        $guard = $this->getGuard();

        return $guard ? 'guest:'.$guard : 'guest';
    }

    /**
     * Get the login username to be used by the controller.
     *
     * @return string
     */
    public function loginUsername()
    {
        return property_exists($this, 'username') ? $this->username : 'email';
    }

    /**
     * Determine if the class is using the ThrottlesLogins trait.
     *
     * @return bool
     */
    protected function isUsingThrottlesLoginsTrait()
    {
        return in_array(
            ThrottlesLogins::class, class_uses_recursive(static::class)
        );
    }

    /**
     * Get the guard to be used during authentication.
     *
     * @return string|null
     */
    protected function getGuard()
    {
        return property_exists($this, 'guard') ? $this->guard : null;
    }
}

然后我们再看RegistersUsers.php

这个主要处理getregister,postregister

vendor/laravel/framework/src/Illuminate/Foundation/Auth/RegistersUsers.php

< ?php

namespace Illuminate\Foundation\Auth;

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

trait RegistersUsers
{
    use RedirectsUsers;

    /**
     * Show the application registration form.
     *
     * @return \Illuminate\Http\Response
     */
    public function getRegister() //这里就是getRegister
    {
        return $this->showRegistrationForm();
    }

    /**
     * Show the application registration form.
     *
     * @return \Illuminate\Http\Response
     */
    public function showRegistrationForm()  //其实调用的是他
    {
        if (property_exists($this, 'registerView')) {
            return view($this->registerView);
        }

        return view('auth.register');  //看逻辑可以知道,如果没有registerView的话就用auth.register来作为注册页,原理跟login差不多
    }

    /**
     * Handle a registration request for the application.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function postRegister(Request $request) //这里是postRegister
    {
        return $this->register($request);
    }

    /**
     * Handle a registration request for the application.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function register(Request $request)  //其实是用他,这里有点复杂
    {
        $validator = $this->validator($request->all());  


        if ($validator->fails()) {  //会先去判断是否能够通过validator,而这个validator就是之前在AuthController.php的那个,而且这个throwValidationException(并不是在页面的显示错误的
                                    //是在这里storage/logs/laravel.log
            $this->throwValidationException(
                $request, $validator
            );
        }

        Auth::guard($this->getGuard())->login($this->create($request->all())); 
        //这里通过调用getGuard来判断是否确认写入数据库,这里首先通过create写入数据库,然后进行login登录,登录成功了,就是下面的回调页面了。好巧妙。

        return redirect($this->redirectPath()); //注册成功返回的那个回调页面,也是在AuthController.php配
    }

    /**
     * Get the guard to be used during registration.
     *
     * @return string|null
     */
    protected function getGuard()
    {

        return property_exists($this, 'guard') ? $this->guard : null;  //这个就是判断auth.php里的guard的。
    }
}

然后我们配置登录页面

resources/views/auth/login.blade.php

@extends('layout.app')

@section('content')

    <div class="col-md-4 col-md-offset-4">
        {!! Form::open(['url'=>'auth/login']) !!}  //这里跟路由表配置要相匹配,post提交到auth/login
                <!--- Email Field --->
        <div class="form-group">
            {!! Form::label('email', 'Email:') !!}     //登录项有2个,一个是email一个是password
            {!! Form::email('email', null, ['class' => 'form-control']) !!}
        </div>

        <!--- Password Field --->
        <div class="form-group">
            {!! Form::label('password', 'Password:') !!}
            {!! Form::password('password', ['class' => 'form-control']) !!}
        </div>


        {!! Form::submit('登录',['class'=>'btn btn-primary form-control']) !!}

        {!! Form::close() !!}
    </div>
    <ul class="list-group">   //这个代码是额外的,主要是为了看验证失败的时候的报错信息,laravel会将错误信息写到$errors里面去,所以能够在页面获取来看
        @foreach($errors->all() as $error)
            <li class="list-group-item list-group-item-danger">{{$error}}</li>
        @endforeach
    </ul>
@stop

然后我们配置注册页面

这里我们有4个字段,有3个事必须的,name,password,email,因为这个对应AuthController的create方法的值,其实这个也是跟model的表有关,因为我们的user表也就是使用这3个字段来做验证的。

resources/views/auth/register.blade.php

@extends('layout.app')

@section('content')

    <div class="col-md-4 col-md-offset-4">
        {!! Form::open(['url'=>'auth/register']) !!}  //注意这里是post到auth/register

                <!--- Name Field --->
        <div class="form-group">
            {!! Form::label('name', 'Name:') !!}    
            {!! Form::text('name', null, ['class' => 'form-control']) !!}
        </div>
        <!--- Email Field --->
        <div class="form-group">
            {!! Form::label('email', 'Email:') !!}
            {!! Form::email('email', null, ['class' => 'form-control']) !!}
        </div>

        <!--- Password Field --->
        <div class="form-group">
            {!! Form::label('password', 'Password:') !!}
            {!! Form::password('password', ['class' => 'form-control']) !!}
        </div>
       <!--- Password-confirm Field --->
        <div class="form-group">
            {!! Form::label('password_confirmation', 'Password_confirmation:') !!}  //需要注意的是,这个password_confirmation是有讲究的,如果不是这样写的话,会导致validator验证不通过
            {!! Form::password('password_confirmation', ['class' => 'form-control']) !!}
        </div>

        {!! Form::submit('注册',['class'=>'btn btn-primary form-control']) !!}

        {!! Form::close() !!}
    </div>
        <ul class="list-group">
        @foreach($errors->all() as $error)
            <li class="list-group-item list-group-item-danger">{{$error}}</li>
        @endforeach
    </ul>
@stop

然后我们看AuthenticatesUsers.php

vendor/laravel/framework/src/Illuminate/Foundation/Auth/AuthenticatesUsers.php

    public function getLogout()   //这里就是getLogout
    {
        return $this->logout();
    }

    /**
     * Log the user out of the application.
     *
     * @return \Illuminate\Http\Response
     */
    public function logout()  //其实是他
    {
        Auth::guard($this->getGuard())->logout();

        return redirect(property_exists($this, 'redirectAfterLogout') ? $this->redirectAfterLogout : '/auth/login');  
        //这里需要注意的是,这里logout的重定向地址需要设置一下,默认是/但是如果/是要登录才可以看的话,那么就会出错。
    }

然后我们再看AuthController.php

app/Http/Controllers/Auth/AuthController.php


    protected $redirectTo = '/articles'; //刚才我们提到登录成功的重定向地址就是这个$redirectTo
    protected $guard = 'web';  //这个guard是特别的,是因为laravel5.2的关系

对此官网的解释

Guard Customization

You may also customize the "guard" that is used to authenticate users. To get started, define a guard property on your AuthController. The value of this property should correspond with one of the guards configured in your auth.php configuration file:

protected $guard = 'admin';

你要设置一个guard的值,并且要跟auth.php对应好,然后我们再看看auth.php

config/auth.php
< ?php

return [

    /*
    |--------------------------------------------------------------------------
    | Authentication Defaults
    |--------------------------------------------------------------------------
    |
    | This option controls the default authentication "guard" and password
    | reset options for your application. You may change these defaults
    | as required, but they're a perfect start for most applications.
    |
    */

    'defaults' => [
        'guard' => 'web',  //默认指定了一个guard 是叫web的
        'passwords' => 'users',
    ],

    /*
    |--------------------------------------------------------------------------
    | Authentication Guards
    |--------------------------------------------------------------------------
    |
    | Next, you may define every authentication guard for your application.
    | Of course, a great default configuration has been defined for you
    | here which uses session storage and the Eloquent user provider.
    |
    | All authentication drivers have a user provider. This defines how the
    | users are actually retrieved out of your database or other storage
    | mechanisms used by this application to persist your user's data.
    |
    | Supported: "session", "token"
    |
    */


    'guards' => [
        'web' => [  //然后这个叫web的guard呢有driver和provider这些属性,一个是session 驱动,一个是users的provider,简单理解就是用users表和session来做guard,这个guard可以理解为校验
            'driver' => 'session',
            'provider' => 'users',
        ],

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

    /*
    |--------------------------------------------------------------------------
    | User Providers
    |--------------------------------------------------------------------------
    |
    | All authentication drivers have a user provider. This defines how the
    | users are actually retrieved out of your database or other storage
    | mechanisms used by this application to persist your user's data.
    |
    | If you have multiple user tables or models you may configure multiple
    | sources which represent each model / table. These sources may then
    | be assigned to any extra authentication guards you have defined.
    |
    | Supported: "database", "eloquent"
    |
    */

    'providers' => [
        'users' => [  //这里再次解释了users的这个provider就是一个eloquent,就是model Users
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],

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

];

注册成功后会有数据在数据库生成
检查数据库

id    name    email    password    remember_token    created_at    updated_at
1    123456    1239@qq.com    $2y$10$EfEo1gCcK6JdwgxjqjNbK.fVZjgu7i68uKMPqNwBX9VpNVuvgthm6    wSaR4V256k4xxisbbiVNS1o9iEqwCaIDZB5Nk5YZYj5JNBENIiowTALrBNNT    2016-05-25 15:31:07    2016-05-25 15:41:53

每次登录成功都会有一个laravel_session,而guard就是校验这个东西的,判断是否能登陆之类。

原文链接:http://www.godblessyuan.com/2016/05/26/laravel-5-2-%e7%94%a8%e6%88%b7%e6%b3%a8%e5%86%8c%e5%92%8c%e7%99%bb%e5%bd%95/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值