Symfony 6.4+React+JWT登录报错:key 'email'需为字符串,传入NULL
问题:JWT登录报错“The key 'email' must be a string, 'NULL' given”
使用Symfony 6.4、React、API Platform和LexikJWTAuthentication开发时,API已通过JWT正常保护,但实现登录跳转仪表盘功能时,出现上述错误。请求参数中email和密码均非空,相关配置如下:
相关配置
security.yml
security: enable_authenticator_manager: true password_hashers: Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto' providers: app_user_provider: entity: class: App\Entity\User property: email firewalls: dev: pattern: ^/{_{profiler|wdt}}/ security: false login: pattern: ^/api/login stateless: true form_login: check_path: /api/login_check username_parameter: email password_parameter: password default_target_path: app_dashboard success_handler: lexik_jwt_authentication.handler.authentication_success failure_handler: lexik_jwt_authentication.handler.authentication_failure api: pattern: ^/api/ stateless: true jwt: ~ access_control: - { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/api, roles: IS_AUTHENTICATED_FULLY } when@test: security: password_hashers: Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: algorithm: auto cost: 4 time_cost: 3 memory_cost: 10
lexik_jwt_authentication.yml
lexik_jwt_authentication: secret_key: '%env(resolve:JWT_SECRET_KEY)%' public_key: '%env(resolve:JWT_PUBLIC_KEY)%' pass_phrase: '%env(JWT_PASSPHRASE)%' token_ttl: 3600 api_platform: check_path: /api/login_check username_path: email password_path: security.credentials.password
Login.jsx
const Login = () => { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const handleEmailChange = (e) => setEmail(e.target.value); const handlePasswordChange = (e) => setPassword(e.target.value); const handleSubmit = async (e) => { e.preventDefault(); try { const response = await axios.post( 'https://localhost/index.php/api/login_check', {email, password}, { headers: { 'Content-Type': 'application/json', }, } ); console.log('Login successful:', response.data); } catch (error) { console.error('Error during login:', error); } }; return ( <form onSubmit={handleSubmit}> <Input type="email" variant="bordered" size="lg" label="Email" placeholder="Enter your email" labelPlacement="outside" className="pt-5 pb-5" value={email} id="email" name="_email" onChange={handleEmailChange} /> <Input type="password" variant="bordered" size="lg" label="Password" placeholder="Enter your password" labelPlacement="outside" className="pt-5 pb-12" value={password} id="password" name="_password" onChange={handlePasswordChange} /> <CustomButton label="Login" type="submit"/> </form> )
请求参数示例
{"email":"admin@test.com","password":"test"}
解决思路
修正LexikJWT的password_path配置
当前password_path: security.credentials.password是针对表单提交的嵌套路径,但你使用JSON直接提交password字段,需改为:# lexik_jwt_authentication.yml api_platform: check_path: /api/login_check username_path: email password_path: password移除无状态认证中的跳转配置
login防火墙设置了stateless: true,无状态认证不需要后端跳转,default_target_path会干扰JWT认证流程,删除security.yml中form_login下的该配置:# security.yml的login防火墙部分 form_login: check_path: /api/login_check username_parameter: email password_parameter: password # 移除 default_target_path: app_dashboard success_handler: lexik_jwt_authentication.handler.authentication_success failure_handler: lexik_jwt_authentication.handler.authentication_failure替换form_login为json_login
form_login默认处理表单格式(x-www-form-urlencoded),而你用JSON提交,改用json_login更适配API场景:# security.yml的login防火墙部分 login: pattern: ^/api/login stateless: true json_login: check_path: /api/login_check username_path: email password_path: password success_handler: lexik_jwt_authentication.handler.authentication_success failure_handler: lexik_jwt_authentication.handler.authentication_failure验证User实体的标识符方法
Symfony 6+中UserInterface用getUserIdentifier()替代getUsername(),确保User实体返回email作为标识符:// src/Entity/User.php public function getUserIdentifier(): string { return (string) $this->email; }统一表单字段name属性
React表单Input的name为_email、_password,但提交的JSON字段是email、password,将name改为一致,避免潜在解析问题:<Input // ...其他属性 name="email" onChange={handleEmailChange} /> <Input // ...其他属性 name="password" onChange={handlePasswordChange} />
内容的提问来源于stack exchange,提问作者balrcoding
相关产品推荐
相关产品推荐

