覆盖 laravel 4 的身份验证方法以使用自定义 hasing 函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15306196/
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 07:36:40  来源:igfitidea点击:

Override laravel 4's authentication methods to use custom hasing function

phplaravellaravel-4

提问by Christian

I have a table in my database with users. Their password are generated with my own custom hashing function.

我的数据库中有一个包含用户的表。他们的密码是用我自己的自定义散列函数生成的。

How do i override the Authentication methods in laravel 4 to use my own hash class?

我如何覆盖 laravel 4 中的身份验证方法以使用我自己的哈希类?

This is what I have been trying to do:

这就是我一直在尝试做的:

    class CustomUserProvider implements Illuminate\Auth\UserProviderInterface {


    public function retrieveByID($identifier)
    {
        return $this->createModel()->newQuery()->find($identifier);
    }

    public function retrieveByCredentials(array $credentials)
    {
        // First we will add each credential element to the query as a where clause.
        // Then we can execute the query and, if we found a user, return it in a
        // Eloquent User "model" that will be utilized by the Guard instances.
        $query = $this->createModel()->newQuery();

        foreach ($credentials as $key => $value)
        {
            if ( ! str_contains($key, 'password')) $query->where($key, $value);
        }

        return $query->first();
    }

    public function validateCredentials(Illuminate\Auth\UserInterface $user, array $credentials)
    {
        $plain = $credentials['password'];

        return $this->hasher->check($plain, $user->getAuthPassword());
    }

}

class CodeIgniter extends Illuminate\Auth\Guard {


}

App::bind('Illuminate\Auth\UserProviderInterface', 'CustomUserProvider');



Auth::extend('codeigniter', function()
{
    return new CodeIgniter( App::make('CustomUserProvider'), App::make('session'));
});

When I run the Auth::attempt method I get this error: ErrorException: Warning: Illegal offset type in isset or empty in G:\Dropbox\Workspaces\www\video\vendor\laravel\framework\src\Illuminate\Foundation\Application.php line 352

当我运行 Auth::attempt 方法时,我收到此错误:ErrorException: Warning: Illegal offset type in isset or empty in G:\Dropbox\Workspaces\www\video\vendor\laravel\framework\src\Illuminate\Foundation\Application .php 第 352 行

回答by Christian

This is how ended up solving the problem:

这就是最终解决问题的方式:

libraries\CustomHasherServiceProvider.php

图书馆\CustomHasherServiceProvider.php

use Illuminate\Support\ServiceProvider;

class CustomHasherServiceProvider extends ServiceProvider {

    public function register()
    {
        $this->app->bind('hash', function()
        {
            return new CustomHasher;
        });
    }

}

libraries\CustomHasher.php

图书馆\CustomHasher.php

class CustomHasher implements Illuminate\Hashing\HasherInterface {

private $NUMBER_OF_ROUNDS = '$rounds=7331$';


public function make($value, array $options = array())
{

    $salt = uniqid();
    $hash = crypt($password, $this->NUMBER_OF_ROUNDS . $salt);
    return substr($hash, 15);
}

public function check($value, $hashedValue, array $options = array())
{
    return $this->NUMBER_OF_ROUNDS . $hashedValue === crypt($value, $this->NUMBER_OF_ROUNDS . $hashedValue);
}

}

And then I replaced 'Illuminate\Hashing\HashServiceProvider' with 'CustomHasherServiceProvider' in the providers array in app/config/app.php

然后我在 app/config/app.php 的 providers 数组中用 'CustomHasherServiceProvider' 替换了 'Illuminate\Hashing\HashServiceProvider'

and added "app/libraries" to autoload classmap in composer.json

并添加了“应用程序/库”以在 composer.json 中自动加载类映射

回答by MrCasual

@vFragosop was on the right path with extending Auth.

@vFragosop 在扩展Auth.

There are a couple of ways to skin the cat and here is how I would do that without replacing the default Hasherclass:

有几种方法可以给猫剥皮,这里是我将如何在不替换默认Hasher类的情况下做到这一点:

Include in your app/routes.phpor wherever:

包括在您app/routes.php或任何地方:

use Illuminate\Auth\Guard;
Auth::extend("eloquent", function() {
    return new Guard(
        new \Illuminate\Auth\EloquentUserProvider(new CustomHasher(), "User"),  
        App::make('session.store')
    );
});

Create and autoload a CustomHasherclass (i.e., app/libraries/CustomHasher.php):

创建并自动加载一个CustomHasher类(即app/libraries/CustomHasher.php):

class CustomHasher extends Illuminate\Hashing\BcryptHasher {
    public function make($value, array $options = array())
    {
        ...
    }
    public function check($value, $hashedValue, array $options = array())
    {
        ...
    }
}

That's it.

就是这样。

回答by vFragosop

Warning:I can't ensure this is works out of the box and there may be a few gotchas here and there. Keep in mind Laravel 4 is still on development. Wish I could provide a more precise answer, but codebase is still going through many changes and not everything is properly documented. Anyway, you are looking for something like this:

警告:我不能确保这是开箱即用的,这里和那里可能有一些问题。请记住,Laravel 4 仍在开发中。希望我能提供更准确的答案,但代码库仍在经历许多更改,并且并非所有内容都被正确记录。无论如何,您正在寻找这样的东西:

// on config/auth.php
'driver' => 'custom'
// on start/global.php
Auth::extend('custom', function() {
    // CustomUserProvider is your custom driver and should
    // implement Illuminate\Auth\UserProviderInterface;
    return new Guard(new CustomUserProvider, App::make('session'));
});

If this doesn't give you enough information to start, you should be able to figure it out by taking a look at those classes below:

如果这没有为您提供足够的信息来开始,您应该能够通过查看以下这些类来弄清楚:

EloquentUserProviderand DatabaseUserProvider
These classes are the currently supported authentication drivers. They should guide you on how to create your CustomUserProvider(or any name you like really).

EloquentUserProviderDatabaseUserProvider
这些类是当前支持的身份验证驱动程序。他们应该指导您如何创建您的CustomUserProvider(或您真正喜欢的任何名称)。

Manager
This is the base class for anything that accepts custom drivers (including the AuthManager). It provides the methods for registering them like you do in Laravel 3.

Manager
这是任何接受自定义驱动程序(包括AuthManager)的基类。它提供了注册它们的方法,就像你在 Laravel 3 中所做的那样。

回答by musicin3d

This was the top result on Google, but these answers are insufficient for anyone on Laravel 5. Even the documentation doesn't suffice.

这是 Google 上的最高结果,但这些答案对于 Laravel 5 上的任何人来说都不够。即使是文档也不够。

I've successfully replaced the Hasher for only the UserProvider. The rest of my application continues to use the very nice BcryptHasher, while user authentication uses a custom hasher. To do this, I had to study these answers, the documentation, and Laravel's source code itself. Here's what I found. Hopefully I can save someone else's full head of hair. Feel free to crosspost this to a question about Laravel 5.

我已经成功地为 UserProvider 替换了 Hasher。我的应用程序的其余部分继续使用非常好的 BcryptHasher,而用户身份验证使用自定义散列器。为此,我必须研究这些答案、文档和 Laravel 的源代码本身。这是我发现的。希望我能拯救别人的满头头发。随意将此交叉发布到有关 Laravel 5 的问题中。



First, create your custom hasher, if you haven't already. Place it wherever you'd like.

首先,创建您的自定义散列器(如果您还没有的话)。把它放在任何你喜欢的地方。

class MyCustomHasher implements Hasher {

    public function make($value, array $options = []) {
        return md5( $value );  // PLEASE DON'T USE MD5!
    }

    public function check($value, $hashedValue, array $options = []) {
        if (strlen($hashedValue) === 0) {
            return false;
        }
        return $hashedValue === $this->make($value);
    }

    public function needsRehash($hashedValue, array $options = []) {
        return false;
    }

}


Edit any registered ServiceProvideras follows...

编辑任何注册ServiceProvider如下...

class AppServiceProvider extends ServiceProvider {

    public function boot() {
        Auth::provider('eloquentCustom', function ($app, $config) {
            return new EloquentUserProvider(new MyCustomHasher(), $config['model']);
        });
    }

}

You can replace 'eloquentCustom'with whatever you'd prefer.

你可以'eloquentCustom'用你喜欢的任何东西替换。



Finally, edit your config/auth.phpto use your custom provider. Here are the relevant parts...

最后,编辑您config/auth.php以使用您的自定义提供程序。以下是相关部分...

return [

    // ...

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        // ...
    ],

    // ...

    'providers' => [
        'users' => [
            'driver' => 'eloquentCustom',  // <--- This is the only change
            'model' => App\User::class,
        ],
        // ...
    ],

    // ...

];




Here's a little explanation, because I can't believe how obscure this was.

这里有一点解释,因为我无法相信这是多么晦涩难懂。

As you may expect, authentication is configured with config/auth.php. There are two key parts: Guards and Providers. I haven't yet bothered to learn exactly what guards do, but they seem to enforce authentication requirements. Providers are responsible for providing the necessary information to the guards. Therefore, a Guard requires a Provider. You can see that, in the default configuration, guards.web.provideris mapped to providers.users.

正如您所料,身份验证是使用config/auth.php. 有两个关键部分:Guards 和 Providers。我还没有费心去了解守卫究竟做了什么,但他们似乎强制执行身份验证要求。提供者负责向警卫提供必要的信息。因此,Guard 需要 Provider。您可以看到,在默认配置中,guards.web.provider映射到providers.users.

Laravel provides two implementations of UserProviderby default: EloquentUserProviderand DatabaseUserProvider. These correspond to the two possible values for providers.users.driver: eloquentand database, respectively. Normally, the eloquentoption is chosen. EloquentUserProviderneeds a Hasher, so Laravel gives it whatever the standard implementation is (ie. BcryptHasher). We override this behavior by creating our own "driver" for instantiating the Provider.

LaravelUserProvider默认提供了两种实现:EloquentUserProviderDatabaseUserProvider。它们分别对应于providers.users.driver:eloquent和的两个可能值database。通常,eloquent选择该选项。EloquentUserProvider需要一个Hasher,所以 Laravel 给它任何标准实现是(即。BcryptHasher)。我们通过创建我们自己的“驱动程序”来实例化提供程序来覆盖此行为。

Authis our friendly neighborhood facade. It is backed by the AuthManager. The often suggested Auth::extend()method expects a Guard(contrary to what the documentation might suggest). We have no need to mess with the Guard. Instead, we can use Auth::provider()which basically does the same thing as extend(), except it expects a Provider. So we provide a function to create our own instance of a EloquentUserProvider, giving it our custom Hasher (eg. MyCustomHasher). We also include a driver "name" that can be used in the config file.

Auth是我们友好的邻里门面。它由AuthManager. 通常建议的Auth::extend()方法需要一个Guard(与文档可能建议的相反)。我们没必要去惹守卫。相反,我们可以使用Auth::provider()which 基本上与 做同样的事情extend(),除了它需要一个 Provider。所以我们提供了一个函数来创建我们自己的 a 实例EloquentUserProvider,给它我们的自定义哈希器(例如MyCustomHasher)。我们还包括一个可以在配置文件中使用的驱动程序“名称”。

Now back to the config file. That driver name that we just created is now a valid value for providers.users.driver. Set it there and you're good to go!

现在回到配置文件。我们刚刚创建的驱动程序名称现在是 的有效值providers.users.driver。把它放在那里,你就可以开始了!

I hope this all makes sense and is useful for someone!

我希望这一切都有意义并且对某人有用!