如何创建 Laravel 5.1 自定义身份验证驱动程序?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32243363/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 12:16:00  来源:igfitidea点击:

How to create Laravel 5.1 Custom Authentication driver?

phplaravellaravel-5laravel-5.1

提问by scott

I am working in Laravel authentication login using socialite. Now I can able to save data of user from socialite. But now I am facing problem how to authenticate user from gmail, github.

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

After some research I understood that I need to create custom authentication. I googled but all are Laravel 4.1 topics. If any one work on this please provide your answers.

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

I already read following topics but I didn't got how to do it?

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

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

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

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

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

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

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

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

Update

更新

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
    ]);
}

回答by Rash

This answer is most suited for Laravel 5.1. Please take care if you are in some other version. Also keep in mind that IMHO this is a rather advanced level in Laravel, and hence if you don't fully understand what you are doing, you may end up crashing your application. The solution is not end to end correct. This is just a general guideline of what you need to do in order for this to work.

这个答案最适合 Laravel 5.1。如果您使用的是其他版本,请小心。还要记住,恕我直言,这是 Laravel 中相当高级的级别,因此如果您不完全了解自己在做什么,最终可能会导致应用程序崩溃。解决方案不是端到端正确的。这只是您需要做什么才能使其正常工作的一般指南。

Adding Custom Authentication Drivers In Laravel 5.1

在 Laravel 5.1 中添加自定义身份验证驱动程序

Hint:Laravel documentation for this topic is here.

提示:该主题的 Laravel 文档在这里

Hint2:The last link you mentioned is quite useful in my opinion. I learned all of this after reading that link.

提示2:您提到的最后一个链接在我看来非常有用。阅读该链接后,我了解了所有这些。

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

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



Before we start, I would first like to describe the login flow which will help you understand the process. Laravel uses a driverto connect to the database to fetch your records. Two drivers come pre-bundled with laravel - eloquent& database. We want to create a third so that we can customize it to our needs.

在开始之前,我想先描述一下登录流程,这将有助于您理解这个过程。Laravel 使用 adriver连接到数据库以获取您的记录。两个驱动程序预先捆绑了 laravel - eloquent& database。我们想创建第三个,以便我们可以根据需要对其进行自定义。

Illuminate\Auth\Guardinside your vendor folder is the main file which has code for the user to log in and log out. And this file mainly uses two Contracts (or interfaces)that we need to override in order for our driver to work. From Laravel's own documentation read this:

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

The Illuminate\Contracts\Auth\UserProvider implementations are only responsible for fetching a Illuminate\Contracts\Auth\Authenticatable implementation out of a persistent storage system, such as MySQL, Riak, etc. These two interfaces allow the Laravel authentication mechanisms to continue functioning regardless of how the user data is stored or what type of class is used to represent it.

Illuminate\Contracts\Auth\UserProvider 实现只负责从持久化存储系统(例如 MySQL、Riak 等)中获取 Illuminate\Contracts\Auth\Authenticatable 实现。这两个接口允许 Laravel 身份验证机制继续发挥作用用户数据的存储方式或用于表示它的类的类型。

So the idea is that for our driver to work we need to implement Illuminate\Contracts\Auth\UserProviderand Illuminate\Contracts\Auth\Authenticatableand tell Laravel to use these implementations instead of the defaults.

这样的想法是,我们的司机工作,我们需要实现Illuminate\Contracts\Auth\UserProviderIlluminate\Contracts\Auth\Authenticatable告诉Laravel改为使用默认的这些实现。



So let's begin.

那么让我们开始吧。

Step 1:Choose a name for your driver. I name mine socialite. Then in your config/auth.php, change the drivername to socialite. By doing this we just told laravel to use this driver for authentication instead of eloquentwhich is default.

Step 1:为您的驱动程序选择一个名称。我的名字是我的socialite。然后在您的 中config/auth.php,将driver名称更改为socialite. 通过这样做,我们只是告诉 laravel 使用此驱动程序进行身份验证,而不是eloquent默认使用。

Step 2:In your app/Provider/AuthServiceProviderin the boot()method add the following lines:

Step 2:在您app/Provider/AuthServiceProviderboot()方法中添加以下几行:

Auth::extend('socialite', function($app) {
    $provider = new SocialiteUserProvider();
    return new AuthService($provider, App::make('session.store'));
});

What we did here is:

我们在这里做的是:

  • We first used Authfacade to define the socialitedriver.
  • SocialiteUserProvideris an implementation of UserProvider.
  • AuthServiceis my extension of Guardclass. The second parameter this class's constructor takes is the session which laravel uses to get and set sessions.
  • So we basically told Laravel to use our own implementation of Guardclass instead of the default one.
  • 我们首先使用AuthFacade 来定义socialite驱动程序。
  • SocialiteUserProvider是 的实现UserProvider
  • AuthService是我的Guard班级延伸。这个类的构造函数采用的第二个参数是 Laravel 用来获取和设置会话的会话。
  • 所以我们基本上告诉 Laravel 使用我们自己的Guard类实现而不是默认的。

Step 3:Create SocialiteUserProvider. If you read the Laravel's documentation, you will understand what each of these methods should return. I have created the first method as a sample. As you can see, I use my UserServiceclass to fetch results. You can fetch your own results however you want to fetch them. Then I created an Userobject out of it. This Userclass implements the Illuminate\Contracts\Auth\Authenticatablecontract.

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:Create Userclass which implements the Authenticatable. This class has to implement this interface because the Guardclass will use this class to get values.

Step 4:创建User实现Authenticatable. 这个类必须实现这个接口,因为这个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:Finally create the AuthService class that will call the Guardmethods. This is my own implementation. You can write your own as per your needs. What we have done here is extended the Guardclass to implement two new functions which are self explanatory.

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 StepJust to complete my answer, I will also explain the structure that UserServiceclass expects. First lets understand what this class does. In our above steps we created everything to let laravel know how to use our authentication driver, instead of theirs. But we still haven't told laravel that how should it get the data. All we told laravel that if you call the userService->getUserByEmail($email)method, you will get your data. So now we simply have to implement this function.

Step 6: Bonus Step为了完成我的回答,我还将解释UserService类所期望的结构。首先让我们了解这个类是做什么的。在我们上面的步骤中,我们创建了一切让 laravel 知道如何使用我们的身份验证驱动程序,而不是他们的。但是我们还没有告诉laravel它应该如何获取数据。我们告诉 laravel 如果你调用这个userService->getUserByEmail($email)方法,你会得到你的数据。所以现在我们只需要实现这个功能。

E.g.1 You are using Eloquent.

例如 1 您正在使用Eloquent.

public function getUserByEmail($email)
{
    return UserModel::where('email', $email)->get();
}

E.g.2 You are using Fluent.

例如 2 您正在使用Fluent.

public function getUserByEmail($email)
{
    return DB::table('myusertable')->where('email', '=', $email)->get();
}

Update: 19 Jun 2016

更新:2016 年 6 月 19 日

Thank you @skittles for pointing out that I have not clearly shown where the files should be placed.All the files are to be placed as per the namespace given. E.g. if the namespace is App\Extensionsand the class name is SocialiteUserProviderthen location of file is App\Extensions\SocialiteUserProvider.php. The Appdirectory in laravel is the appfolder.

谢谢@skittles 指出我没有清楚地显示文件应该放在哪里。所有文件都将按照给定的命名空间放置。例如,如果命名空间是App\Extensions并且类名是SocialiteUserProvider那么文件的位置是App\Extensions\SocialiteUserProvider.php. 将App在laravel目录是app文件夹。

回答by nathanmac

Good tutorial for setting up laravel socialite here: https://mattstauffer.co/blog/using-github-authentication-for-login-with-laravel-socialite

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

Auth::logindoesn't return a boolean value you can use attempt to do a Auth::attempt

Auth::login不返回一个布尔值,你可以尝试做一个 Auth::attempt

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

Follow the tutorial and do this, and just have middleware configured on the home route

按照教程做这个,只需要在home路由上配置中间件

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

Auth::login($authUser, true);

return Redirect::to('home');