这个答案最适合 Laravel 5.1。请注意如果你
在其他版本中。还要记住,恕我直言,这是 Laravel 中相当高级的级别,因此如果您不完全了解自己在做什么,您最终可能会导致应用程序崩溃。解决方案不是端到端正确的。这只是您需要执行哪些操作才能使其正常工作的一般准则。
在 Laravel 5.1 中添加自定义身份验证驱动程序
提示:此主题的 Laravel 文档是 here。
提示2:您提到的最后一个链接在我看来非常有用。阅读该链接后,我了解了所有这些。
http://laravel.io/forum/11-04-2014-laravel-5-how-do-i-create-a-custom-auth-in-laravel-5
在我们开始之前,我想先描述一下登录流程,这将有助于您理解该过程。 Laravel 使用 driver 连接到数据库以获取您的记录。两个驱动程序预先与 laravel 捆绑在一起 - eloquent 和 database。我们想创建第三个,以便我们可以根据需要对其进行自定义。
Illuminate\Auth\Guard 在您的供应商文件夹中是主文件,其中包含用户登录和注销的代码。这个文件主要使用了两个Contracts (or interfaces),我们需要覆盖它们才能让我们的驱动程序工作。从 Laravel 自己的文档中阅读:
Illuminate\Contracts\Auth\UserProvider 实现仅
负责获取 Illuminate\Contracts\Auth\Authenticatable
从持久存储系统(例如 MySQL)中实现,
Riak 等。这两个接口允许 Laravel 认证
无论用户数据如何,都可以继续运行的机制
存储或使用什么类型的类来表示它。
所以我们的想法是,为了让我们的驱动程序工作,我们需要实现 Illuminate\Contracts\Auth\UserProvider 和 Illuminate\Contracts\Auth\Authenticatable 并告诉 Laravel 使用这些实现而不是默认值。
让我们开始吧。
Step 1:
为您的驱动程序选择一个名称。我命名我的socialite。然后在您的config/auth.php 中,将driver 名称更改为socialite。通过这样做,我们只是告诉 laravel 使用此驱动程序进行身份验证,而不是默认的 eloquent。
Step 2:
在boot() 方法中的app/Provider/AuthServiceProvider 中添加以下行:
Auth::extend('socialite', function($app) {
$provider = new SocialiteUserProvider();
return new AuthService($provider, App::make('session.store'));
});
我们在这里所做的是:
- 我们首先使用
Auth 外观来定义socialite 驱动程序。
-
SocialiteUserProvider 是 UserProvider 的实现。
-
AuthService 是我对 Guard 类的扩展。这个类的构造函数的第二个参数是 laravel 用来获取和设置会话的会话。
- 所以我们基本上告诉 Laravel 使用我们自己实现的
Guard 类,而不是默认的。
Step 3:
创建SocialiteUserProvider。如果您阅读 Laravel 的文档,您将了解这些方法中的每一个应该返回什么。我创建了第一个方法作为示例。如您所见,我使用我的UserService 类来获取结果。您可以获取自己的结果,但是您想获取它们。然后我创建了一个User 对象。这个User 类实现了Illuminate\Contracts\Auth\Authenticatable 合约。
<?php
namespace App\Extensions;
use App\User;
use App\Services\UserService;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\UserProvider;
class SocialiteUserProvider implements UserProvider
{
private $userService;
public function __construct(UserService $userService)
{
$this->userService = $userService;
}
public function retrieveById($identifier)
{
$result = $this->userService->getUserByEmail($identifier);
if(count($result) === 0)
{
$user = null;
}
else
{
$user = new User($result[0]);
}
return $user;
}
public function retrieveByToken($identifier, $token)
{
// Implement your own.
}
public function updateRememberToken(Authenticatable $user, $token)
{
// Implement your own.
}
public function retrieveByCredentials(array $credentials)
{
// Implement your own.
}
public function validateCredentials(Authenticatable $user, array $credentials)
{
// Implement your own.
}
}
Step 4:
创建实现Authenticatable 的User 类。这个类必须实现这个接口,因为Guard 类会使用这个类来获取值。
<?php
namespace App;
use Illuminate\Contracts\Auth\Authenticatable;
class User implements Authenticatable
{
protected $primaryKey = 'userEmail';
protected $attributes = [];
public function __construct(array $attributes)
{
$this->attributes = $attributes;
}
public function getUserAttributes()
{
return $this->attributes;
}
public function getAuthIdentifier()
{
return $this->attributes[$this->primaryKey];
}
public function getAuthPassword()
{
// Implement your own.
}
public function getRememberToken()
{
// Implement your own.
}
public function setRememberToken($value)
{
// Implement your own.
}
public function getRememberTokenName()
{
// Implement your own.
}
}
Step 5:
最后创建将调用Guard 方法的AuthService 类。这是我自己的实现。您可以根据自己的需要编写自己的。我们在这里所做的是扩展Guard 类以实现两个不言自明的新功能。
<?php
namespace App\Services;
use Illuminate\Auth\Guard;
class AuthService extends Guard
{
public function signin($email)
{
$credentials = array('email' => $email);
$this->fireAttemptEvent($credentials, false, true);
$this->lastAttempted = $user = $this->provider->retrieveById($email);
if($user !== null)
{
$this->login($user, false);
return true;
}
else
{
return false;
}
}
public function signout()
{
$this->clearUserDataFromStorage();
if(isset($this->events))
{
$this->events->fire('auth.logout', [$this->user()]);
}
$this->user = null;
$this->loggedOut = true;
}
}
Step 6: Bonus Step
为了完成我的回答,我还将解释UserService 类所期望的结构。首先让我们了解这个类的作用。在我们上面的步骤中,我们创建了所有东西来让 laravel 知道如何使用我们的身份验证驱动程序,而不是他们的。但是我们还没有告诉 laravel 它应该如何获取数据。我们告诉 laravel,如果你调用 userService->getUserByEmail($email) 方法,你会得到你的数据。所以现在我们只需要实现这个功能。
例如1您正在使用Eloquent。
public function getUserByEmail($email)
{
return UserModel::where('email', $email)->get();
}
例如2您正在使用Fluent。
public function getUserByEmail($email)
{
return DB::table('myusertable')->where('email', '=', $email)->get();
}
更新:2016 年 6 月 19 日
感谢@skittles 指出我没有清楚地显示文件应该放在哪里。所有文件都应该按照给定的命名空间放置。例如。如果命名空间是App\Extensions,类名是SocialiteUserProvider,那么文件的位置是App\Extensions\SocialiteUserProvider.php。 laravel 中的App 目录就是app 文件夹。