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

后端 未结 4 695
长发绾君心
长发绾君心 2021-02-08 16:09

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

4条回答
  •  庸人自扰
    2021-02-08 16:41

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

    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.


    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 ServiceProvider as follows...

    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.


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

    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.provider is mapped to 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!

提交回复
热议问题