You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony5新认证系统自定义哈希器报createHasher()参数类型错误

问题根因
  1. 接口实现类型错误
    Symfony 安全组件的password_hashers配置项中指定的自定义哈希器服务,必须实现Symfony\Component\PasswordHasher\PasswordHasherInterface接口,你当前实现的UserPasswordHasherInterface属于上层业务工具接口,不是给底层哈希工厂消费的。哈希工厂读取配置时,没有识别到你传入的是合法的哈希器实例,误将其当做配置数组处理,所以抛出了参数必须为数组,实际为对象的错误。
  2. 方法逻辑与配置缺陷
  • 你写的ShaOneEncoder中isPasswordValid方法直接使用了未定义的$salt、$encoded变量,运行时会抛出变量未定义错误。
  • needsRehash方法返回true,会导致Symfony每次登录都尝试重写用户密码,如果你没有实现重哈希后的密码落库逻辑,就会出现登录成功后会话状态异常,触发无限重定向,这也是你用auto算法时出现死循环的核心原因。
修复方案

1. 调整自定义哈希器实现

将ShaOneEncoder改为实现PasswordHasherInterface,适配安全组件的调用规则:

<?php
namespace App\Security;

use Symfony\Component\PasswordHasher\PasswordHasherInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;

class ShaOneEncoder implements PasswordHasherInterface
{
    private $params;
    
    public function __construct(ParameterBagInterface $params)
    {
        $this->params = $params;
    }

    /**
     * 生成哈希(命令行哈希密码、手动创建用户时调用,需要salt上下文时可自行扩展)
     */
    public function hash(string $plainPassword): string
    {
        throw new \RuntimeException('生成哈希需传入用户salt,可调用encodePassword方法手动传入salt');
    }

    /**
     * 校验密码(登录时安全组件自动调用,会自动传入用户的salt字段)
     */
    public function verify(string $hashedPassword, string $plainPassword, string $salt = null): bool
    {
        if (null === $salt) {
            throw new \InvalidArgumentException('当前哈希器必须依赖用户salt校验密码');
        }
        $separator = $this->params->get('standard.passwd_separator');
        return sha1($plainPassword . $separator . $salt) === $hashedPassword;
    }

    /**
     * 判断是否需要重哈希,遗留系统直接返回false即可
     */
    public function needsRehash(string $hashedPassword): bool
    {
        return false;
    }

    /**
     * 手动生成哈希的工具方法,用于创建用户等场景
     */
    public function encodePassword(string $rawPassword, string $salt): string
    {
        $separator = $this->params->get('standard.passwd_separator');
        return sha1($rawPassword . $separator . $salt);
    }
}

2. 修正LoginFormAuthenticator的响应逻辑

检查onAuthenticationSuccess方法,必须返回跳转响应,避免登录成功后无响应导致的跳转异常:

public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
    // 跳转到登录前的页面或者首页
    return new RedirectResponse($this->urlGenerator->generate('home'));
}

3. 保持security.yaml配置不变

你当前的哈希器配置已经符合要求,不需要调整。

补充说明

你观察到的接口行为差异是正常设计:

  • PasswordHasherInterface是底层哈希器的标准接口,安全组件的校验、哈希逻辑都会直接调用该接口的方法。
  • UserPasswordHasherInterface是封装后的业务工具类接口,仅用于业务代码中手动调用哈希/校验逻辑,不会被安全组件的哈希工厂识别。

内容的提问来源于stack exchange,提问作者akio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 16:09:03