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

时间:2013-03-09 01:40:52

标签: php laravel laravel-4

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

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

这就是我一直在努力做的事情:

    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:警告:isset中的非法偏移类型或G:\ Dropbox \ Workspaces \ www \ video \ vendor \ laravel \ framework \ src \ Illuminate \ Foundation \ Application.php第352行中为空

4 个答案:

答案 0 :(得分: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数组中用'CustomHasherServiceProvider'替换'Illuminate \ Hashing \ HashServiceProvider'

并将“app / libraries”添加到composer.json

中的自动加载类映射中

答案 1 :(得分: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())
    {
        ...
    }
}

就是这样。

答案 2 :(得分: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中那样注册它们的方法。

答案 3 :(得分: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.web.provider被映射到providers.users

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

Auth是我们友好的社区门面。它由AuthManager支持。经常建议使用的Auth::extend()方法期望使用Guard(与文档可能建议的相反)。我们没有必要与警卫队混为一谈。取而代之的是,我们可以使用Auth::provider(),它与extend()的功能基本相同,只是需要提供者。因此,我们提供了一个函数来创建我们自己的EloquentUserProvider实例,并为其提供了自定义的Hasher(例如MyCustomHasher)。我们还包括一个可在配置文件中使用的驱动程序“名称”。

现在返回配置文件。我们刚刚创建的驱动程序名称现在是providers.users.driver的有效值。将其设置在那里,您就可以开始了!

我希望这一切对所有人都有帮助!