9

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

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

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

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

当我运行 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 行

4

4 回答 4

15

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

库\CustomHasherServiceProvider.php

use Illuminate\Support\ServiceProvider;

class CustomHasherServiceProvider extends ServiceProvider {

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

}

库\CustomHasher.php

class CustomHasher implements Illuminate\Hashing\HasherInterface {

private $NUMBER_OF_ROUNDS = '$5$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);
}

}

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

并在 composer.json 中添加了“app/libraries”来自动加载类映射

于 2013-03-09T16:02:43.807 回答
4

@vFragosop 是在正确的道路上扩展Auth.

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

包括在您的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')
    );
});

创建并自动加载一个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())
    {
        ...
    }
}

就是这样。

于 2013-11-15T17:08:41.327 回答
1

警告:我不能确保这是开箱即用的,可能会有一些问题。请记住,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'));
});

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

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

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

于 2013-03-09T02:51:42.813 回答
0

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

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


首先,创建您的自定义哈希(如果您还没有的话)。把它放在你想要的任何地方。

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

}

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

class AppServiceProvider extends ServiceProvider {

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

}

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


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

return [

    // ...

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

    // ...

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

    // ...

];


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

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

Laravel provides two implementations of UserProvider by default: EloquentUserProvider and DatabaseUserProvider. These correspond to the two possible values for providers.users.driver: eloquent and database, respectively. Normally, the eloquent option is chosen. EloquentUserProvider needs 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.

Auth is 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.

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!

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

于 2019-01-22T01:14:22.850 回答