【问题标题】:How to create Laravel 5.1 Custom Authentication driver?如何创建 Laravel 5.1 自定义身份验证驱动程序?
【发布时间】:2015-11-21 11:32:39
【问题描述】:

我正在使用社交名流进行 Laravel 身份验证登录。现在我可以从社交名流中保存用户的数据。但现在我面临如何从 gmail、github 验证用户的问题。

经过一些研究,我了解到我需要创建自定义身份验证。我用谷歌搜索,但都是 Laravel 4.1 主题。如果有人在这方面工作,请提供您的答案。

我已经阅读了以下主题,但我不知道该怎么做?

http://laravel.com/docs/5.1/authentication#social-authentication

http://laravel.com/docs/5.1/providers

http://laravel-recipes.com/recipes/115/using-your-own-authentication-driver

http://laravel.io/forum/11-04-2014-laravel-5-how-do-i-create-a-custom-auth-in-laravel-5

更新

public function handleProviderCallback() {
    $user = Socialite::with('github')->user();
    $email=$user->email;
    $user_id=$user->id;

    //$authUser = User::where('user_id',$user_id)->where('email', $email)->first();
    $authUser = $this->findOrCreateUser($user);

    if(Auth::login($authUser, true)) {
        return Redirect::to('user/UserDashboard');
    }   
}

private function findOrCreateUser($user) {
    if ($authUser = User::where('user_id',$user->id)->first()) {
        return $authUser;
    }

    return User::create([
        'user_id' => $user->id,
        'name' => $user->nickname,
        'email' => $user->email,
        'avatar' => $user->avatar
    ]);
}

【问题讨论】:

  • 您认为为什么需要创建自定义身份验证? Socialite 有适用于 Google 和 GitHub 的驱动程序。
  • @MartinBean.i 是 laravel 的新手。我可以保存数据,但现在我面临如何进行身份验证的问题

标签: php laravel laravel-5 laravel-5.1


【解决方案1】:

这个答案最适合 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 捆绑在一起 - eloquentdatabase。我们想创建第三个,以便我们可以根据需要对其进行自定义。

Illuminate\Auth\Guard 在您的供应商文件夹中是主文件,其中包含用户登录和注销的代码。这个文件主要使用了两个Contracts (or interfaces),我们需要覆盖它们才能让我们的驱动程序工作。从 Laravel 自己的文档中阅读:

Illuminate\Contracts\Auth\UserProvider 实现仅 负责获取 Illuminate\Contracts\Auth\Authenticatable 从持久存储系统(例如 MySQL)中实现, Riak 等。这两个接口允许 Laravel 认证 无论用户数据如何,都可以继续运行的机制 存储或使用什么类型的类来表示它。

所以我们的想法是,为了让我们的驱动程序工作,我们需要实现 Illuminate\Contracts\Auth\UserProviderIlluminate\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 驱动程序。
  • SocialiteUserProviderUserProvider 的实现。
  • 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: 创建实现AuthenticatableUser 类。这个类必须实现这个接口,因为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-&gt;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 文件夹。

【讨论】:

  • 您能告诉我们您的 UserService 课程吗?这是使您的答案完整的唯一缺少的东西。
  • @LastTemplar 你好。我已经更新了我的答案,应该适合您的需求。不幸的是,我无法添加自己的 UserService 类,因为我使用了几层代码来获取我的数据。我使用存储库模式。但对你来说,它应该就像我在我的例子中展示的那样。如果您需要更多信息,请告诉我。编码愉快!
  • @Rash - 如果您更具体地了解您说要创建的每个文件的位置,您的建议可能会更有价值。如果您提供的帮助给读者带来的问题远远多于解决的问题,这将是非常可怕的。
  • @Skittles 谢谢你的建议。但是,您能否更具体地说明您认为需要进行更多更改的地方?根据 PSR4 标准,命名空间指示文件需要位于的位置。这也是默认的 laravel 项目结构,所以这里的事情应该是不言自明的。如果您能指出需要更多信息的地方,我会很高兴,我会考虑这些变化。
  • @Skittles 这是一个公平的观点。我已经在我的答案底部更新了我的答案。 PSR4 是人们现在在他们的代码中实现的 PHP 编码标准。比如你的文件名应该是什么,应该放在哪里,使用空格而不是制表符,以及其他类似的东西。
【解决方案2】:

在这里设置 laravel 社交名流的好教程:https://mattstauffer.co/blog/using-github-authentication-for-login-with-laravel-socialite

Auth::login 不返回布尔值,您可以尝试使用 Auth::attempt

if(Auth::login($authUser, true)) {
    return Redirect::to('user/UserDashboard');
}

按照教程执行此操作,只需在主路由上配置中间件

$authUser = $this->findOrCreateUser($user);

Auth::login($authUser, true);

return Redirect::to('home');

【讨论】:

  • @nathanmac.it 登录后会返回空白页面
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-16
  • 2017-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-01
  • 1970-01-01
相关资源
最近更新 更多