1.用户认证主要涉及到几个方面

AuthServiceProvider

AuthManager

Guard模块, 以TokenGuard为例

   配置文件中的config/auth.php

2. 先可以看下系统默认的LoginController定义

<?php

namespace App\Http\Controllers\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;

/**
* Where to redirect users after login.
*
* @var string
*/
protected $redirectTo = '/home';

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


这里的主要作用是  use AuthenticatesUsers;主要作用的也是这个类

<?php

namespace Illuminate\Foundation\Auth;

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

trait AuthenticatesUsers
{
use RedirectsUsers, ThrottlesLogins;

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

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

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

if ($this->attemptLogin($request)) {
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.
$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->username() => 'required', 'password' => 'required',
]);
}

/**
* Attempt to log the user into the application.
*
* @param \Illuminate\Http\Request $request
* @return bool
*/
protected function attemptLogin(Request $request)
{
return $this->guard()->attempt(
$this->credentials($request), $request->has('remember')
);
}

/**
* 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');
}

/**
* Send the response after the user was authenticated.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
protected function sendLoginResponse(Request $request)
{
$request->session()->regenerate();

$this->clearLoginAttempts($request);

return $this->authenticated($request, $this->guard()->user())
?: redirect()->intended($this->redirectPath());
}

/**
* The user has been authenticated.
*
* @param \Illuminate\Http\Request $request
* @param mixed $user
* @return mixed
*/
protected function authenticated(Request $request, $user)
{
//
}

/**
* Get the failed login response instance.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse
*/
protected function sendFailedLoginResponse(Request $request)
{
$errors = [$this->username() => trans('auth.failed')];

if ($request->expectsJson()) {
return response()->json($errors, 422);
}

return redirect()->back()
->withInput($request->only($this->username(), 'remember'))
->withErrors($errors);
}

/**
* Get the login username to be used by the controller.
*
* @return string
*/
public function username()
{
return 'email';
}

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

$request->session()->flush();

$request->session()->regenerate();

return redirect('/');
}

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


这里的登录逻辑是

   1. 判断用户名密码不能为空

   2. 登录失败错误次数不能超过一定次数

   3. 可以看下attempLogin的实现是这样的

/**
* Attempt to log the user into the application.
*
* @param \Illuminate\Http\Request $request
* @return bool
*/
protected function attemptLogin(Request $request)
{
return $this->guard()->attempt(
$this->credentials($request), $request->has('remember')
);
}

    guard函数是这样的

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

 Auth的服务提供这是在AuthServiceProvider,该类定义是

<?php

namespace Illuminate\Auth;

use Illuminate\Auth\Access\Gate;
use Illuminate\Support\ServiceProvider;
use Illuminate\Contracts\Auth\Access\Gate as GateContract;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;

class AuthServiceProvider extends ServiceProvider
{
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->registerAuthenticator();

$this->registerUserResolver();

$this->registerAccessGate();

$this->registerRequestRebindHandler();
}

/**
* Register the authenticator services.
*
* @return void
*/
protected function registerAuthenticator()
{
$this->app->singleton('auth', function ($app) {
// Once the authentication service has actually been requested by the developer
// we will set a variable in the application indicating such. This helps us
// know that we need to set any queued cookies in the after event later.
$app['auth.loaded'] = true;

return new AuthManager($app);
});

$this->app->singleton('auth.driver', function ($app) {
return $app['auth']->guard();
});
}

/**
* Register a resolver for the authenticated user.
*
* @return void
*/
protected function registerUserResolver()
{
$this->app->bind(
AuthenticatableContract::class, function ($app) {
return call_user_func($app['auth']->userResolver());
}
);
}

/**
* Register the access gate service.
*
* @return void
*/
protected function registerAccessGate()
{
$this->app->singleton(GateContract::class, function ($app) {
return new Gate($app, function () use ($app) {
return call_user_func($app['auth']->userResolver());
});
});
}

/**
* Register a resolver for the authenticated user.
*
* @return void
*/
protected function registerRequestRebindHandler()
{
$this->app->rebinding('request', function ($app, $request) {
$request->setUserResolver(function ($guard = null) use ($app) {
return call_user_func($app['auth']->userResolver(), $guard);
});
});
}
}


也就是说Auth的真实服务是 AuthManager,看下这个类的guard和getDefaultConfig

/**
* Resolve the given guard.
*
* @param string $name
* @return \Illuminate\Contracts\Auth\Guard|\Illuminate\Contracts\Auth\StatefulGuard
*
* @throws \InvalidArgumentException
*/
protected function resolve($name)
{
$config = $this->getConfig($name);

if (is_null($config)) {
throw new InvalidArgumentException("Auth guard [{$name}] is not defined.");
}

if (isset($this->customCreators[$config['driver']])) {
return $this->callCustomCreator($name, $config);
}

$driverMethod = 'create'.ucfirst($config['driver']).'Driver';

if (method_exists($this, $driverMethod)) {
return $this->{$driverMethod}($name, $config);
}

throw new InvalidArgumentException("Auth guard driver [{$name}] is not defined.");
}


/**
* Get the default authentication driver name.
*
* @return string
*/
public function getDefaultDriver()
{
return $this->app['config']['auth.defaults.guard'];
}


/**
* Attempt to get the guard from the local cache.
*
* @param string $name
* @return \Illuminate\Contracts\Auth\Guard|\Illuminate\Contracts\Auth\StatefulGuard
*/
public function guard($name = null)
{
$name = $name ?: $this->getDefaultDriver();

return isset($this->guards[$name])
? $this->guards[$name]
: $this->guards[$name] = $this->resolve($name);
}


这样就生成了一个Guard,可以使用Token,Session等等,继续看TokenGuard的attempt函数,该函数只有在sessionGuard的时候采用,可以看下auth.php文件

'guards' => [
'web' => [
'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' => [
'driver' => 'eloquent',
'model' => App\User::class,
],

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


上面的guards的providers的users和下面的providers的users是一一对应的,Guard的还有一个user函数和id获得当前用户对应和当前用户ID的方法

public function user()
{
// If we've already retrieved the user for the current request we can just
// return it back immediately. We do not want to fetch the user data on
// every call to this method because that would be tremendously slow.
if (! is_null($this->user)) {
return $this->user;
}

$user = null;

$token = $this->getTokenForRequest();

if (! empty($token)) {
$user = $this->provider->retrieveByCredentials(
[$this->storageKey => $token]
);
}

return $this->user = $user;
}


获得参数中的token值,然后利用provider进行,用户对象查询,而provider函数,而provider则是

'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],


可以看下类

EloquentUserProvider的定义


public function retrieveByCredentials(array $credentials)
{
if (empty($credentials)) {
return;
}

// First we will add each credential element to the query as a where clause.
// Then we can execute the query and, if we found a user, return it in a
// Eloquent User "model" that will be utilized by the Guard instances.
$query = $this->createModel()->newQuery();

foreach ($credentials as $key => $value) {
if (! Str::contains($key, 'password')) {
$query->where($key, $value);
}
}

return $query->first();
}

这样我们拿到token值和TokenGuard中token存储的键值,在数据库中进行查找即可,就得到了User对象,而ID函数,则是在

GuardHelpers中定义的,获得user对象的id,以及check等函数