在新的 Laravel 应用上运行
php artisan make:auth和php artisan migrate命令。就可以构建好整个认证系统。
Laravel 中实现用户认证非常简单,几乎所有的东西都为你配置好了。其配置文件位于 config/auth.php,包含了相关的选项配置。
其核心由 Laravel 的认证组件「看守器」和「提供器」组成。
看守器定义了该如何认证每个请求中的用户。例如,Laravel 自带的 session 看守器会使用 session 存储和 cookies 来维护状态。
提供器定义了该何如从持久化的存储数据中检索用户。Laravel 自带支持使用 Eloquent 和数据库查询构造器来检索用户。当然,你也可以根据需要自定义其他提供器。
不过对于大多数应用而言,可能永远不需要修改默认身份认证配置。
默认情况下,Laravel 在 app 目录中包含了一个 Eloquent 模型 App\User。这个模型和默认的 Eloquent 认证驱动一起使用。如果不打算使用 Eloquent,也可以使用 Laravel 查询构造器的 database 认证驱动。
Laravel 默认使用 email 字段来认证。如果要使用其他字段认证,可以在 LoginController 中定义一个 username 方法:
public function username()
{
return 'username';
}还可以自定义用于认证和注册用户的「看守器」。要实现这一功能,需要在 LoginController、RegisterController 和 ResetPasswordController 中定义 guard 方法。该方法需要返回一个看守器实例:
use Illuminate\Support\Facades\Auth;
protected function guard()
{
return Auth::guard('guard-name');
}看守器 web 实例是这样的:
SessionGuard {#436 ▼
#name: "web"
#lastAttempted: null
#viaRemember: false
#session: Store {#378 ▶}
#cookie: CookieJar {#366 ▶}
#request: Request {#55 ▶}
#events: Dispatcher {#35 ▶}
#loggedOut: false
#recallAttempted: false
#user: null
#provider: EloquentUserProvider {#431 ▶}
}看守器 api 实例是这样的:
TokenGuard {#431 ▼
#request: Request {#55 ▶}
#inputKey: "api_token"
#storageKey: "api_token"
#user: null
#provider: EloquentUserProvider {#432 ▶}
}可以通过 Auth facade 来访问认证的用户:
use Illuminate\Support\Facades\Auth;
// 获取当前已认证的用户
$user = Auth::user();
// 获取当前已认证的用户 ID
$id = Auth::id();或者,还可以通过 Illuminate\Http\Request 实例来访问已认证的用户。类型提示的类会被自动注入到控制器方法中。
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ProfileController extends Controller
{
public function update(Request $request)
{
// $request->user() 返回已认证的用户实例
}
}可以使用 Auth facade 的 check 方法来检查用户是否登录,如果已认证,将会返回 true。
use Illuminate\Support\Facades\Auth;
if (Auth::check()) {
// 用户已登录
}即使可以使用
check方法来确定用户是否被认证,通常,在允许用户访问某些路由或控制器之前,还是会使用中间件来验证用户是否进行身份验证。
路由中间件只允许通过认证的用户访问指定的路由。Laravel 自带了在 Illuminate\Auth\Middleware\Authenticate 中定义的 auth 中间件。由于这个中间件已经在 HTTP 内核中注册,所以只需要将中间件附加到路由定义中:
Route::get('profile', function () {
// 只有认证过的用户可以
})->middleware('auth');当然,如果是控制器,则可以在构造函数中调用:
public function __construct()
{
$this->middleware('auth');
}当 auth 中间件检测到一个未认证的用户时,会返回一个 401 的 JSON 响应,或者如果检测到不是 AJAX 请求,会重定向到名为 login 的路由。
可以在 app/Exceptions/Handler.php 中重写 unauthenticated 方法来进行修改:
use Illuminate\Auth\AuthenticationException;
protected function unauthenticated($request, AuthenticationException $exception)
{
return $request->expectsJson()
? response()->json(['message' => $exception->getMessage()], 401)
: redirect()->guest(route('login'));
}将 auth 中间件添加到路由时,还需要指定使用哪个看守器来认证用户。指定的看守器对应配置文件 auth.php 中 guards 数组的某个键:
public function __construct()
{
$this->middleware('auth:api');
}如果不指定,默认使用第一个。
Laravel 内置的控制器 LoginController 已经包含了 Illuminate\Foundation\Auth\ThrottlesLogins trait。默认情况下,如果用户在进行几次尝试后仍不能提供正确的凭证,该用户将在一分钟内无法进行登录。这个限制基于用户的用户名、邮箱地址和 IP 地址。
可以使用 Auth facade 的 extend 方法来定义自己的身份验证提供器。需要在服务提供器中调用这个提供器,由于 Laravel 已经配备了 AuthServiceProvider,我们可以把代码放在这个提供器内:
namespace App\Providers;
use App\Services\Auth\JwtGuard;
use Illuminate\Support\Facades\Auth;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
$this->registerPolicies();
Auth::extend('jwt', function ($app, $name, array $config) {
// 返回一个 Illuminate\Contracts\Auth\Guard 实例
return new JwtGuard(Auth::createUserProvider($config['provider']));
});
}
}正如上面的代码所示,传递给 extend 方法的回调应该返回 Illuminate\Contracts\Auth\Guard 接口实现的实例。这个接口包含自定义看守器必须的方法。定义之后,就可以在 auth.php 配置文件的 guards 配置中使用了。
'guards' => [
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],如果没有使用传统的关系数据库来存储用户信息,则需要使用自己的用户认证提供器来扩展。我们使用 Auth facade 上的 provider 方法自定义用户提供器:
namespace App\Providers;
use Illuminate\Support\Facades\Auth;
use App\Extensions\RiakUserProvider;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
$this->registerPolicies();
Auth::provider('riak', function ($app, array $config) {
// 返回 Illuminate\Contracts\Auth\UserProvider 实例
return new RiakUserProvider($app->make('riak.connection'));
});
}
}使用 provider 方法注册用户提供器后,就可以在配置文件 auth.php 中切换到新的用户提供器。首先,定义一个使用新驱动的 provider:
'providers' => [
'users' => [
'driver' => 'riak',
],
],最后,在 guards 配置中使用这个提供器:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
],Laravel 在认证过程中引发了各种各样的事件。可以在 EventServiceProvider 中对这些事件做监听:
protected $listen = [
'Illuminate\Auth\Events\Registered' => [
'App\Listeners\LogRegisteredUser',
],
'Illuminate\Auth\Events\Attempting' => [
'App\Listeners\LogAuthenticationAttempt',
],
'Illuminate\Auth\Events\Authenticated' => [
'App\Listeners\LogAuthenticated',
],
'Illuminate\Auth\Events\Login' => [
'App\Listeners\LogSuccessfulLogin',
],
'Illuminate\Auth\Events\Failed' => [
'App\Listeners\LogFailedLogin',
],
'Illuminate\Auth\Events\Logout' => [
'App\Listeners\LogSuccessfulLogout',
],
'Illuminate\Auth\Events\Lockout' => [
'App\Listeners\LogLockout',
],
'Illuminate\Auth\Events\PasswordReset' => [
'App\Listeners\LogPasswordReset',
],
];