欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

laravel 5.2 用户注册和登录

程序员文章站 2024-04-03 11:06:10
...
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.phpRoute::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.phpmiddleware($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    

然后我们再看AuthenticatesUsers

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

vendor/laravel/framework/src/Illuminate/Foundation/Auth/AuthenticatesUsers.phpshowLoginForm();    }    /**     * 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.phpshowRegistrationForm();    }    /**     * 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')    
{!! Form::open(['url'=>'auth/login']) !!} //这里跟路由表配置要相匹配,post提交到auth/login
{!! Form::label('email', 'Email:') !!} //登录项有2个,一个是email一个是password {!! Form::email('email', null, ['class' => 'form-control']) !!}
{!! Form::label('password', 'Password:') !!} {!! Form::password('password', ['class' => 'form-control']) !!}
{!! Form::submit('登录',['class'=>'btn btn-primary form-control']) !!} {!! Form::close() !!}
    //这个代码是额外的,主要是为了看验证失败的时候的报错信息,laravel会将错误信息写到$errors里面去,所以能够在页面获取来看 @foreach($errors->all() as $error)
  • {{$error}}
  • @endforeach
@stop

然后我们配置注册页面

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

resources/views/auth/register.blade.php@extends('layout.app')@section('content')    
{!! Form::open(['url'=>'auth/register']) !!} //注意这里是post到auth/register
{!! Form::label('name', 'Name:') !!} {!! Form::text('name', null, ['class' => 'form-control']) !!}
{!! Form::label('email', 'Email:') !!} {!! Form::email('email', null, ['class' => 'form-control']) !!}
{!! Form::label('password', 'Password:') !!} {!! Form::password('password', ['class' => 'form-control']) !!}
{!! Form::label('password_confirmation', 'Password_confirmation:') !!} //需要注意的是,这个password_confirmation是有讲究的,如果不是这样写的话,会导致validator验证不通过 {!! Form::password('password_confirmation', ['class' => 'form-control']) !!}
{!! Form::submit('注册',['class'=>'btn btn-primary form-control']) !!} {!! Form::close() !!}
    @foreach($errors->all() as $error)
  • {{$error}}
  • @endforeach
@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 CustomizationYou 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 [        '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_at1   123456  1239@qq.com $2y$10$EfEo1gCcK6JdwgxjqjNbK.fVZjgu7i68uKMPqNwBX9VpNVuvgthm6    wSaR4V256k4xxisbbiVNS1o9iEqwCaIDZB5Nk5YZYj5JNBENIiowTALrBNNT    2016-05-25 15:31:07 2016-05-25 15:41:53

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