Yii(Php Crypt)和Laravel Sentinel之间的哈希密码兼容性



我正在使用Sentinel构建一个laravel应用程序,该应用程序基于Yii中的旧系统代码。

目的是能够与旧用户/旧数据库一起登录新系统。

我首先必须解决模型问题:

自定义模型和字段与Sentinel/Laravel

现在,一切都好了。

我有最后一个问题,它似乎是从不同的方式散列密码。

当我在Yii中检查哈希方法时,我可以发现它使用Blowfish算法:

    /**
 * CPasswordHelper provides a simple API for secure password hashing and verification.
 *
 * CPasswordHelper uses the Blowfish hash algorithm available in many PHP runtime
 * environments through the PHP {@link http://php.net/manual/en/function.crypt.php crypt()}
 * built-in function. As of Dec 2012 it is the strongest algorithm available in PHP
 * and the only algorithm without some security concerns surrounding it. For this reason,
 * CPasswordHelper fails to initialize when run in and environment that does not have
 * crypt() and its Blowfish option. Systems with the option include:
 * (1) Most *nix systems since PHP 4 (the algorithm is part of the library function crypt(3));
 * (2) All PHP systems since 5.3.0; (3) All PHP systems with the
 * {@link http://www.hardened-php.net/suhosin/ Suhosin patch}.
 * For more information about password hashing, crypt() and Blowfish, please read
 * the Yii Wiki article
 * {@link http://www.yiiframework.com/wiki/425/use-crypt-for-password-storage/ Use crypt() for password storage}.
 * and the
 * PHP RFC {@link http://wiki.php.net/rfc/password_hash Adding simple password hashing API}.
 *
 * CPasswordHelper throws an exception if the Blowfish hash algorithm is not
 * available in the runtime PHP's crypt() function. It can be used as follows
 *

另一方面,Sentinel管理几种哈希方法:

Native hasher
Bcrypt hasher
Callback hasher
Whirlpool hasher
SHA256 hasher

所以,我猜常见的方法是bcrypt,在我的Laravel模型中,我做到了:

class Administrador extends EloquentUser {
    protected $table = 'administrador';
    protected $fillable = [];
    protected $primaryKey = 'administradorid';
    protected $loginNames = ['correo'];
    protected $guarded = ['administradorid'];
    protected $hidden = ['contrasena', 'remember_token'];
    use SoftDeletes;
    protected $dates = ['deleted_at'];
    /**
     * Set the Sentry User Model Hasher to be the same as the configured Sentry Hasher
     */
    public static function boot()
    {
        parent::boot();
        Sentinel::setHasher(new BcryptHasher);
    }
}

所以说真的,我真的不知道该怎么解决…

此时您可以做的是创建CartalystSentinalHashingHasherInterface的实现,例如:

use CartalystSentinelHashingHasherInterface;
class CombinedHasher implements HasherInterface
{
    /**
     * @var HasherInterface
     */
    private $primary;
    /**
     * @var HasherInterface
     */
    private $fallback;
    /**
     * @param HasherInterface $primary
     * @param HasherInterface $fallback
     */
    public function __construct(HasherInterface $primary, HasherInterface $fallback)
    {
        $this->primary = $primary;
        $this->fallback = $fallback;
    }
    /**
     * Hash the given value.
     *
     * @param  string $value
     * @return string
     * @throws RuntimeException
     */
    public function hash($value)
    {
        return $this->primary->hash($value);
    }
    /**
     * Checks the string against the hashed value.
     *
     * @param  string $value
     * @param  string $hashedValue
     * @return bool
     */
    public function check($value, $hashedValue)
    {
        if ($this->primary->check($value, $hashedValue)) {
            return true;
        }
        return $this->fallback->check($value, $hashedValue);
    }
}

正如您所看到的,它需要HasherInterface的两个实例。因此,在这种情况下,您将首先注入您希望使用的新实现,然后创建接口的实现,该接口实现Yii正在使用的哈希算法。

在检查散列时,它将首先使用新的散列算法。如果返回false,它也将使用回退(Yii算法)进行检查。要创建哈希,它将只使用新的哈希算法。(您可能想为了开发而更改此项,但无论如何都不应该使用生产数据库进行开发。)

所以你接下来要做的是创建一个HasherInterface的实现,它将使用Yii正在使用的哈希算法:

use CartalystSentinelHashingHasherInterface;
class YiiHasher implements HasherInterface
{
    /**
     * Hash the given value.
     *
     * @param  string $value
     * @return string
     * @throws RuntimeException
     */
    public function hash($value)
    {
        // You'll have to implement this
        return yiiHasher($value);
    }
    /**
     * Checks the string against the hashed value.
     *
     * @param  string $value
     * @param  string $hashedValue
     * @return bool
     */
    public function check($value, $hashedValue)
    {
        // You'll have to implement this
        return yiiHashChecker($value, $hashedValue);
    }
}

你必须检查Yii是否有这样的软件包,或者你必须检查他们的源代码,看看它是如何工作的。

所以要使用它,您需要创建一个CombinedHasher的实例,如下所示:

use CartalystSentinelHashingBcryptHasher;
use NamespaceForYourYiiHasher;
$primary = new BcryptHasher();
$fallback = new YiiHasher();
$hasher = new CombinedHasher($primary, $fallback);

更新1:文档中的额外信息

在实际阅读了他们的文档后,我注意到他们还提供了CallbackHasher,这可能需要较少的设置工作:https://cartalyst.com/manual/sentinel/2.0#callback-散列

他们还建议使用NativeHasher而不是BcryptHasher:https://cartalyst.com/manual/sentinel/2.0#native-散列

更新2:在哪里设置

例如,您可以在app/Hashing中创建它们。然后,您必须确保它们具有名称空间AppHashing

要进行设置,您可以使用位于app/Providers/AppServiceProvider.php中的AppServiceProvider

// Import the classes on the top
use AppHashingCombinedHasher;
use AppHashingYiiHasher;
use CartalystSentinelHashingNativeHasher;
// In the AppServiceProvider class itself
public function boot()
{
    $hasher = $this->app['CartalystSentinelHashingHasherInterface'];
    Sentinel::setHasher($hasher);
}
public function register()
{
    $this->app->singleton('CartalystSentinelHashingHasherInterface', function($app) {
        $primary = new NativeHasher();
        $secondary = new YiiHasher();
        return new CombinedHasher($primary, $secondary);
    });
}

最新更新