Auth认证

路由

从路由开始,找到源码,再进行研究
找到根目录下面的

vendor/laravel/framework/src/Illuminate/Routing/Router.php

在282-303之间,具体代码如下:

    /**
     * Register the typical authentication routes for an application.
     *
     * @return void
     */
    public function auth()
    {
        // Authentication Routes...
        $this->get('login', 'Auth\LoginController@showLoginForm')->name('login');
        $this->post('login', 'Auth\LoginController@login');
        $this->post('logout', 'Auth\LoginController@logout');

        // Registration Routes...
        $this->get('register', 'Auth\RegisterController@showRegistrationForm');
        $this->post('register', 'Auth\RegisterController@register');

        // Password Reset Routes...
        $this->get('password/reset', 'Auth\ForgotPasswordController@showLinkRequestForm');
        $this->post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail');
        $this->get('password/reset/{token}', 'Auth\ResetPasswordController@showResetForm');
        $this->post('password/reset', 'Auth\ResetPasswordController@reset');
    }

其中一共有9种路由,登录三种,注册两种,重置密码有四种

登录部分(login)

登录有3种,一种get方式的,两种post方式的,显然get方式的用来获取登录页面,这个没啥好说啦,其中一种POST方式的是用来登出的,也就是logout,一种是登入,也就是login。

login($this->post('login', 'AuthLoginController@login');)

找到

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

(如果不知道怎么找源码的话,直接在编辑器中全局搜索showLoginForm)

在23-56行,就是我们的login方法

/**
     * Handle a login request to the application.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function login(Request $request)
    {
        $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.
        if ($lockedOut = $this->hasTooManyLoginAttempts($request)) {
            $this->fireLockoutEvent($request);

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

        $credentials = $this->credentials($request);

        if ($this->guard()->attempt($credentials, $request->has('remember'))) {
            return $this->sendLoginResponse($request);
        }

        // 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 (! $lockedOut) {
            $this->incrementLoginAttempts($request);
        }

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

也就是说,我们在页面上面点击登录按钮,就会将请求提交到该方法。
下面我们来看看login方法的具体实现
首先

$this->validateLogin($request);

具体如58~69行:

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

这里只是校验了用户名以及密码是否为非空

回到login方法,校验完后

if ($lockedOut = $this->hasTooManyLoginAttempts($request)) {
    $this->fireLockoutEvent($request);

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

这里面主要是对用户登录失败次数的限制,如果登录失败次数过多就限制用户登录

接着,最重要的部分到啦

$credentials = $this->credentials($request);

具体方法在71~80行,如下:

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

这里返回了request请求里面的‘$this->username()’也就是email字段以及password字段的数据
然后根据上面得到的数据,调用guard()进行用户认证

if ($this->guard()->attempt($credentials, $request->has('remember'))) {
    return $this->sendLoginResponse($request);
}

由guard()具体代码可以看到(152-160行):

/**
 * Get the guard to be used during authentication.
 *
 * @return \Illuminate\Contracts\Auth\StatefulGuard
 */
protected function guard()
{
    return Auth::guard();
}

显然用户的具体账号密码的认证用到了laravel的门面(Facades)来实现最后的用户认证

attempt($credentials, $request->has('remember'))

最后,

if (! $lockedOut) {
    $this->incrementLoginAttempts($request);
}
return $this->sendFailedLoginResponse($request);

如果认证不通过,这里将增加一次失败的次数并返回相对应的信息

经过上面的分析,如果我们不想使用laravel自带的认证的话,我们可以直接使用 Laravel 认证类来管理用户认证,例如

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Auth;

class AuthController extends Controller
{
    /**
     * Handle an authentication attempt.
     *
     * @return Response
     */
    public function authenticate()
    {
        if (Auth::attempt(['email' => $email, 'password' => $password])) {
            // Authentication passed...
            return redirect()->intended('dashboard');
        }
    }
}

attempt 方法接收键值数组对作为第一个参数,数组中的值被用于从数据表中查找用户,因此,在上面的例子中,用户将会通过email 的值获取,如果用户被找到,经哈希运算后存储在数据中的密码将会和传递过来的经哈希运算处理的密码值进行比较。如果两个经哈希运算的密码相匹配那么将会为这个用户开启一个认证Session。

如果认证成功的话 attempt 方法将会返回 true。否则,返回 false。
重定向器上的 intended 方法将用户重定向到登录之前用户想要访问的 URL,在目标 URL 无效的情况下回退 URI 将会传递给该方法。

如果需要的话,除了用户邮件和密码之外还可以在认证查询时添加额外的条件,例如,我们可以验证被标记为有效的用户:

if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
    // The user is active, not suspended, and exists.
}

注:在这些例子中,并不仅仅限于使用 email 进行登录认证,这里只是作为演示示例,你可以将其修改为数据库中任何其他可用作“username”的字段。

最后

如有错误,欢迎指出


QQ交流群:489832466


IMyxuan
335 声望17 粉丝

小墨鱼