Переопределить методы аутентификации laravel 4 для использования пользовательской функции hasing

У меня есть таблица в моей базе данных с пользователями. Их пароль генерируется с помощью моей собственной функции хеширования.

Как переопределить методы аутентификации в 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: Предупреждение: недопустимый тип смещения в isset или пустой в G:\Dropbox\Workspaces\www\video\vendor\laravel\framework\src\Illuminate\Foundation\Application .php строка 352


person Christian    schedule 09.03.2013    source источник


Ответы (4)


Вот так решил проблему:

библиотеки\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);
}

}

Затем я заменил «Illuminate\Hashing\HashServiceProvider» на «CustomHasherServiceProvider» в массиве поставщиков в app/config/app.php.

и добавлено «приложение/библиотеки» для автоматической загрузки карты классов в composer.json

person Christian    schedule 09.03.2013
comment
Я рад видеть, что ссылки помогли вам как-то достичь своей цели. Я надеюсь, что это приключение даст вам некоторое представление о фреймворке. Вы должны пометить свой ответ как принятый, чтобы помочь другим, которые с ним столкнутся. :) - person vFragosop; 10.03.2013
comment
Отличное решение, но чтобы заставить его работать, мне также нужно было реализовать функцию needRehash(), не уверен, что она вообще используется, я просто вернул true... - person Rutger; 29.06.2013
comment
Вы буквально только что поместили «CustomHasherServiceProvider» в массив поставщиков? Я получаю: класс «CustomHasherServiceProvider» не найден - person Henry Ing-Simmons; 02.03.2014
comment
@HenryIng-Simmons да, просто обязательно запустите дамп композитора после создания класса - person Christian; 18.02.2015
comment
Проблема с этим решением заключается в том, что оно полностью заменяет фасад Hash для всего приложения, а не только для аутентификации пользователя. Так что это может быть проблемой, другой код также использует хэш, но вы хотите изменить его только для аутентификации пользователя. См. другие ответы для решений, которые относятся только к аутентификации пользователя. - person orrd; 03.02.2017

@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())
    {
        ...
    }
}

Вот и все.

person MrCasual    schedule 15.11.2013
comment
Это звучало идеально, поскольку Hasher нельзя было заменить во всем приложении. Однако пока это не работает. EloquentUserProvider::validateCredentials() по-прежнему видит BcryptHasher. Я вызываю метод расширения из ServiceProvider::boot(). Есть идеи? - person musicin3d; 22.01.2019
comment
Не бери в голову. Я решил это и добавил свой ответ здесь: stackoverflow.com/a/54299929/839455 - person musicin3d; 22.01.2019

Предупреждение. Я не могу гарантировать, что это работает "из коробки", и здесь и там могут быть некоторые ошибки. Имейте в виду, что 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'));
});

Если это не дает вам достаточно информации для начала, вы сможете понять это, взглянув на эти классы ниже:

EloquentUserProvider и DatabaseUserProvider
Эти классы являются поддерживаемыми в настоящее время драйверами аутентификации. Они должны подсказать вам, как создать свое CustomUserProvider (или любое другое имя, которое вам действительно нравится).

Manager
Это основа класс для всего, что принимает пользовательские драйверы (включая AuthManager). Он предоставляет методы для их регистрации, как в Laravel 3.

person vFragosop    schedule 09.03.2013
comment
Я не могу заставить это работать. Я обновил свою последнюю попытку в вопросе - person Christian; 09.03.2013
comment
Я полагаю, что App::bind вызывает это, не могу понять, что происходит. Вам также не нужно расширять класс Guard, вы можете просто использовать его. Я обновлю свой пример кода с этим. - person vFragosop; 09.03.2013
comment
Я исправил ошибку в методе привязки, и теперь он фактически выполняет функцию retrieveByCredentials. Я постараюсь посмотреть, смогу ли я заставить это работать, и дам вам знать - person Christian; 09.03.2013
comment
Это хорошие новости, если вы просто хотите изменить хэш, вы можете расширить EloquentUserProvider и просто переопределить validateCredentials. - person vFragosop; 09.03.2013
comment
Понятно, но еще лучшим решением было бы изменить только класс хеширования, который использует Auth. Поскольку это единственное, что мне действительно нужно изменить, но я не уверен, как это сделать. - person Christian; 09.03.2013

Это был лучший результат в Google, но этих ответов недостаточно для любого пользователя Laravel 5. Даже документации недостаточно.

Я успешно заменил Hasher только для UserProvider. Остальная часть моего приложения продолжает использовать очень хороший 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 по умолчанию предоставляет две реализации UserProvider: EloquentUserProvider и DatabaseUserProvider. Они соответствуют двум возможным значениям для providers.users.driver: eloquent и database соответственно. Обычно выбирается вариант eloquent. EloquentUserProvider нужен Hasher, поэтому Laravel дает ему стандартную реализацию (т.е. BcryptHasher). Мы переопределяем это поведение, создавая собственный «драйвер» для создания экземпляра Provider.

Auth — фасад нашего дружелюбного соседства. Его поддерживает AuthManager. Часто предлагаемый метод Auth::extend() ожидает Guard (вопреки тому, что может быть предложено в документации). Нам незачем связываться с Гвардией. Вместо этого мы можем использовать Auth::provider(), который в основном делает то же самое, что и extend(), за исключением того, что он ожидает Provider. Поэтому мы предоставляем функцию для создания нашего собственного экземпляра EloquentUserProvider, присваивая ему наш пользовательский хэшер (например, MyCustomHasher). Мы также включаем «имя» драйвера, которое можно использовать в файле конфигурации.

Теперь вернемся к файлу конфигурации. Только что созданное имя драйвера является допустимым значением для providers.users.driver. Установите его там, и все готово!

Я надеюсь, что все это имеет смысл и полезно для кого-то!

person musicin3d    schedule 22.01.2019