Using MD5 in symfony2 security.yml for legacy user

2019-03-16 19:20发布

问题:

I have a legacy system which contains md5 hashed passwords. I have tested these to be correct and they do not use a salt.

security.yml

security:
    encoders:
        Namespace\MyBundle\Entity\User:
            algorithm: md5
providers:
    entityUsers:
        entity: { class: NamespaceBundle:User, property: username }

In my User entity I have implemented UserInterface and made sure the salt is set to the empty string.

But I get a bad credentials error when trying to authenticate.

I have tried switching security.yml to plaintext and entered the hash and the system works fine.

Surely md5 should just work?

回答1:

I was having exactly the same problem and had to dig into the code to find out why.

You don't need to create a custom encoder.

By default, the MessageDigestPasswordEncoder encoder (Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder) in Symfony 2.5 - and possibly all Symfony 2 releases - calculates the MD5 hash of the raw password, with/without using a salt, as expected, and then re-hashes the MD5 a number of times (5000 times, by default, in Symfony 2.5). To make things that little bit more exciting, the encoder will also base64-encode the hash, by default. Both of those features were causing problems for me.

You can fix the problem(s) by disabling the re-hashing and/or disabling the base64 encoding, in security.yml, thus:

security:
    encoders:
        Namespace\Of\Your\User: 
            algorithm: md5
            encode_as_base64: false
            iterations: 0

Hope that saves you some time.



回答2:

Turns out that the md5 in symfony2 uses a salt by default. There may be an easier way, but I just created a custom md5 password encoder interface that ignores salt.

Register a service

namespace.project.md5password.encoder:
    class: Namepspace\MyBundle\Services\CustomMd5PasswordEncoder

Create the encoder service

namespace Namespace\MyBundle\Services;

use Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface;

class CustomMd5PasswordEncoder implements PasswordEncoderInterface
{
    public function __construct() {
    }

    public function encodePassword($raw, $salt) {
        return md5($raw);
    }

    public function isPasswordValid($encoded, $raw, $salt) {
        return md5($raw) == $encoded;
    }
}

Use the new service in security.yml

security:
    encoders:
        Namespace\MyBundle\Entity\User:
            id: namespace.project.md5password.encoder

Hope this helps



标签: php symfony hash