认证
介绍
Laravel 使实现认证变得非常简单。实际上,几乎所有内容都已为您配置好。认证配置文件位于 config/auth.php
,其中包含多个详细记录的选项,用于调整认证服务的行为。
默认情况下,Laravel 在您的 app
目录中包含一个 App\User
模型。此模型可与默认的 Eloquent 认证驱动程序一起使用。
请记住:在为此模型构建数据库架构时,请确保密码列至少为60个字符。此外,在开始之前,请确保您的 users
(或等效)表包含一个可为空的字符串 remember_token
列,长度为100个字符。此列将用于存储应用程序维护的“记住我”会话的令牌。这可以通过在迁移中使用 $table->rememberToken();
来完成。当然,Laravel 5 默认提供了这些列的迁移!
如果您的应用程序不使用 Eloquent,您可以使用 database
认证驱动程序,该驱动程序使用 Laravel 查询构建器。
用户认证
Laravel 默认提供两个与认证相关的控制器。AuthController
处理新用户注册和“登录”,而 PasswordController
包含帮助现有用户重置忘记密码的逻辑。
每个控制器都使用一个 trait 来包含其必要的方法。对于许多应用程序,您无需修改这些控制器。控制器渲染的视图位于 resources/views/auth
目录中。您可以随意自定义这些视图。
用户注册器
要修改新用户注册时所需的表单字段,您可以修改 App\Services\Registrar
类。此类负责验证和创建应用程序的新用户。
Registrar
的 validator
方法包含应用程序新用户的验证规则,而 Registrar
的 create
方法负责在数据库中创建新的 User
记录。您可以随意修改这些方法。Registrar
通过 AuthenticatesAndRegistersUsers
trait 中的方法被 AuthController
调用。
手动认证
如果您选择不使用提供的 AuthController
实现,则需要直接使用 Laravel 认证类来管理用户认证。别担心,这仍然很简单!首先,让我们看看 attempt
方法:
<?php namespace App\Http\Controllers;
use Auth;
use Illuminate\Routing\Controller;
class AuthController extends Controller {
/**
* 处理认证尝试。
*
* @return Response
*/
public function authenticate()
{
if (Auth::attempt(['email' => $email, 'password' => $password]))
{
return redirect()->intended('dashboard');
}
}
}
attempt
方法接受一个键/值对数组作为其第一个参数。password
值将被哈希。数组中的其他值将用于在数据库表中查找用户。因此,在上面的示例中,用户将通过 email
列的值进行检索。如果找到用户,存储在数据库中的哈希密码将与通过数组传递给方法的哈希 password
值进行比较。如果两个哈希密码匹配,将为用户启动一个新的认证会话。
如果认证成功,attempt
方法将返回 true
。否则,将返回 false
。
在此示例中,email
不是必需选项,仅用作示例。您应使用与数据库中“用户名”对应的列名。
intended
重定向函数将用户重定向到他们在被认证过滤器拦截之前尝试访问的 URL。可以为此方法提供一个备用 URI,以防预期的目的地不可用。
使用条件认证用户
您还可以向认证查询添加额外条件:
if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1]))
{
// 用户是活跃的,没有被暂停,并且存在。
}
确定用户是否已认证
要确定用户是否已登录到您的应用程序,可以使用 check
方法:
if (Auth::check())
{
// 用户已登录...
}
认证用户并“记住”他们
如果您希望在应用程序中提供“记住我”功能,可以将布尔值作为第二个参数传递给 attempt
方法,这将使用户无限期地保持认证状态,或直到他们手动注销。当然,您的 users
表必须包含字符串 remember_token
列,该列将用于存储“记住我”令牌。
if (Auth::attempt(['email' => $email, 'password' => $password], $remember))
{
// 用户正在被记住...
}
如果您正在“记住”用户,可以使用 viaRemember
方法来确定用户是否使用“记住我”cookie进行认证:
if (Auth::viaRemember())
{
//
}
通过ID认证用户
要通过用户的ID将其登录到应用程序,请使用 loginUsingId
方法:
Auth::loginUsingId(1);
验证用户凭据而不登录
validate
方法允许您验证用户的凭据,而不实际将其登录到应用程序:
if (Auth::validate($credentials))
{
//
}
为单个请求登录用户
您还可以使用 once
方法将用户登录到应用程序以进行单个请求。不会使用会话或cookie:
if (Auth::once($credentials))
{
//
}
手动登录用户
如果需要将现有用户实例登录到应用程序,可以使用用户实例调用 login
方法:
Auth::login($user);
这相当于使用 attempt
方法通过凭据登录用户。
将用户注销出应用程序
Auth::logout();
当然,如果您使用内置的 Laravel 认证控制器,默认提供了一个处理用户注销出应用程序的控制器方法。
认证事件
当调用 attempt
方法时,将触发 auth.attempt
事件。如果认证尝试成功并且用户已登录,还将触发 auth.login
事件。
检索已认证的用户
一旦用户被认证,有几种方法可以获取用户的实例。
首先,您可以从 Auth
facade 访问用户:
<?php
namespace App\Http\Controllers;
use Auth;
use Illuminate\Routing\Controller;
class ProfileController extends Controller {
/**
* 更新用户的个人资料。
*
* @return Response
*/
public function updateProfile()
{
if (Auth::user())
{
// Auth::user() 返回已认证用户的实例...
}
}
}
其次,您可以通过 Illuminate\Http\Request
实例访问已认证的用户:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
class ProfileController extends Controller {
/**
* 更新用户的个人资料。
*
* @return Response
*/
public function updateProfile(Request $request)
{
if ($request->user())
{
// $request->user() 返回已认证用户的实例...
}
}
}
第三,您可以类型提示 Illuminate\Contracts\Auth\Authenticatable
合约。此类型提示可以添加到控制器构造函数、控制器方法或由服务容器解析的任何其他类的构造函数中:
<?php
namespace App\Http\Controllers;
use Illuminate\Routing\Controller;
use Illuminate\Contracts\Auth\Authenticatable;
class ProfileController extends Controller {
/**
* 更新用户的个人资料。
*
* @return Response
*/
public function updateProfile(Authenticatable $user)
{
// $user 是已认证用户的实例...
}
}
保护路由
路由中间件可用于仅允许已认证用户访问给定路由。Laravel 默认提供 auth
中间件,并在 app\Http\Middleware\Authenticate.php
中定义。您只需将其附加到路由定义:
// 使用路由闭包...
Route::get('profile', ['middleware' => 'auth', function()
{
// 只有已认证用户可以进入...
}]);
// 使用控制器...
Route::get('profile', ['middleware' => 'auth', 'uses' => 'ProfileController@show']);
HTTP基本认证
HTTP基本认证提供了一种快速的方法来认证应用程序的用户,而无需设置专门的“登录”页面。要开始,请将 auth.basic
中间件附加到您的路由:
使用HTTP基本保护路由
Route::get('profile', ['middleware' => 'auth.basic', function()
{
// 只有已认证用户可以进入...
}]);
默认情况下,basic
中间件将使用用户记录上的 email
列作为“用户名”。
设置无状态HTTP基本过滤器
您还可以在不在会话中设置用户标识符cookie的情况下使用HTTP基本认证,这对于API认证特别有用。为此,定义一个中间件,调用 onceBasic
方法:
public function handle($request, Closure $next)
{
return Auth::onceBasic() ?: $next($request);
}
如果您使用PHP FastCGI,HTTP基本认证可能无法正常工作。应将以下行添加到您的 .htaccess
文件中:
RewriteCond %{HTTP:Authorization} ^(.+)$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
密码提醒与重置
模型与表
大多数Web应用程序提供了一种方法,让用户重置他们忘记的密码。Laravel 提供了方便的方法来发送密码提醒和执行密码重置,而不是强迫您在每个应用程序中重新实现这一点。
要开始,请验证您的 User
模型是否实现了 Illuminate\Contracts\Auth\CanResetPassword
合约。当然,框架中包含的 User
模型已经实现了此接口,并使用 Illuminate\Auth\Passwords\CanResetPassword
trait 来包含实现接口所需的方法。
生成提醒表迁移
接下来,必须创建一个表来存储密码重置令牌。此表的迁移已包含在 Laravel 中,并位于 database/migrations
目录中。因此,您只需迁移:
php artisan migrate
密码提醒控制器
Laravel 还包括一个 Auth\PasswordController
,其中包含重置用户密码所需的逻辑。我们甚至提供了视图来帮助您入门!这些视图位于 resources/views/auth
目录中。您可以随意修改这些视图,以适应您自己的应用程序设计。
您的用户将收到一封电子邮件,其中包含指向 PasswordController
的 getReset
方法的链接。此方法将呈现密码重置表单,并允许用户重置其密码。密码重置后,用户将自动登录到应用程序并重定向到 /home
。您可以通过在 PasswordController
上定义 redirectTo
属性来自定义重置后的重定向位置:
protected $redirectTo = '/dashboard';
默认情况下,密码重置令牌在一小时后过期。您可以通过 config/auth.php
文件中的 reminder.expire
选项更改此设置。
社交认证
除了典型的基于表单的认证,Laravel 还提供了一种简单、方便的方法来使用 Laravel Socialite 进行OAuth提供商认证。Socialite 目前支持与 Facebook、Twitter、Google、GitHub 和 Bitbucket 的认证。
要开始使用 Socialite,请在您的 composer.json
文件中包含该包:
"laravel/socialite": "~2.0"
接下来,在您的 config/app.php
配置文件中注册 Laravel\Socialite\SocialiteServiceProvider
。您还可以注册一个facade:
'Socialize' => 'Laravel\Socialite\Facades\Socialite',
您需要为应用程序使用的OAuth服务添加凭据。这些凭据应放置在您的 config/services.php
配置文件中,并应使用 facebook
、twitter
、google
或 github
作为键,具体取决于应用程序所需的提供商。例如:
'github' => [
'client_id' => 'your-github-app-id',
'client_secret' => 'your-github-app-secret',
'redirect' => 'http://your-callback-url',
],
接下来,您可以开始认证用户了!您需要两个路由:一个用于将用户重定向到OAuth提供商,另一个用于在认证后接收来自提供商的回调。以下是使用 Socialize
facade 的示例:
public function redirectToProvider()
{
return Socialize::with('github')->redirect();
}
public function handleProviderCallback()
{
$user = Socialize::with('github')->user();
// $user->token;
}
redirect
方法负责将用户发送到OAuth提供商,而 user
方法将读取传入请求并从提供商处检索用户的信息。在重定向用户之前,您还可以在请求上设置“范围”:
return Socialize::with('github')->scopes(['scope1', 'scope2'])->redirect();
一旦您有了用户实例,您可以获取有关用户的更多详细信息:
检索用户详细信息
$user = Socialize::with('github')->user();
// OAuth Two Providers
$token = $user->token;
// OAuth One Providers
$token = $user->token;
$tokenSecret = $user->tokenSecret;
// All Providers
$user->getId();
$user->getNickname();
$user->getName();
$user->getEmail();
$user->getAvatar();