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

Symfony API登录接口无Header,Angular跨域问题求助

问题描述

API的/api/login_check接口缺少响应头,在Postman中可正常调用,但在Angular项目里无法使用。已知需要添加Access-Control-Allow-Origin: http://localhost:4200响应头,但该接口是内部Symfony控制器,并非本人开发。请问能否覆盖该控制器?或者如何为所有控制器添加固定响应头?

附security.yaml配置:

# https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
password_hashers:
    Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
# https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
providers:
    # used to reload user from session & other features (e.g. switch_user)
    app_user_provider:
        entity:
            class: App\Entity\Usuario
            property: email
    # Usuario con autenticación para la API
    
firewalls:            
    login:
        pattern:  ^/api/login
        stateless: true
        json_login:
            check_path: /api/login_check
            success_handler: lexik_jwt_authentication.handler.authentication_success
            failure_handler: lexik_jwt_authentication.handler.authentication_failure
        http_basic: ~

    api:
        pattern:   ^/api
        stateless: true
        jwt: ~
    
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false

    main:
        lazy: true
        provider: app_user_provider
                   
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
    # - { path: ^/profile, roles: ROLE_USER }
    - { path: ^/admin, roles: ROLE_ADMIN }
    - { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/api,       roles: IS_AUTHENTICATED_FULLY }

when@test:
    security:
        password_hashers:
            # By default, password hashers are resource intensive and take time. This is
            # important to generate secure password hashes. In tests however, secure hashes
            # are not important, waste resources and increase test times. The following
            # reduces the work factor to the lowest possible values.
            Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
                algorithm: auto
                cost: 4 # Lowest possible value for bcrypt
                time_cost: 3 # Lowest possible value for argon
                memory_cost: 10 # Lowest possible value for argon
解决方案

一、全局添加CORS响应头(推荐,无需修改原有控制器)

不需要覆盖任何控制器,通过Symfony内核事件监听给所有响应添加指定头:

  1. 创建事件监听器类src/EventListener/CorsListener.php:
<?php

namespace App\EventListener;

use Symfony\Component\HttpKernel\Event\ResponseEvent;

class CorsListener
{
    public function onKernelResponse(ResponseEvent $event): void
    {
        if (!$event->isMainRequest()) {
            return;
        }

        $response = $event->getResponse();
        // 添加允许的源,可根据环境变量动态配置
        $response->headers->set('Access-Control-Allow-Origin', 'http://localhost:4200');
        // 其他必要的CORS头(可选,根据Angular需求添加)
        $response->headers->set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
        $response->headers->set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
        $response->headers->set('Access-Control-Allow-Credentials', 'true');
    }
}

Symfony 4+默认支持自动注册监听器,无需额外配置services.yaml。

如果要处理OPTIONS预检请求,可添加路由规则:

# config/routes.yaml
options_preflight:
    path: /{regex}
    methods: [OPTIONS]
    requirements:
        regex: ".+"
    controller: Symfony\Bundle\FrameworkBundle\Controller\AbstractController::json
    defaults:
        _controller: Symfony\Bundle\FrameworkBundle\Controller\AbstractController::json
        json: ["", 200]

二、覆盖/api/login_check控制器

若只想针对该接口单独处理,可自定义控制器替代默认逻辑:

  1. 创建自定义控制器src/Controller/CustomLoginCheckController.php:
<?php

namespace App\Controller;

use Lexik\Bundle\JWTAuthenticationBundle\Security\Http\Authentication\AuthenticationSuccessHandler;
use Lexik\Bundle\JWTAuthenticationBundle\Security\Http\Authentication\AuthenticationFailureHandler;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Http\Authentication\JsonAuthentication;

class CustomLoginCheckController
{
    public function __construct(
        private AuthenticationSuccessHandlerInterface $successHandler,
        private AuthenticationFailureHandlerInterface $failureHandler
    ) {}

    public function __invoke(Request $request): Response
    {
        // 复用Symfony的JsonAuthentication逻辑
        $auth = new JsonAuthentication(
            $this->successHandler,
            $this->failureHandler
        );
        $response = $auth->authenticate($request);

        // 添加CORS响应头
        $response->headers->set('Access-Control-Allow-Origin', 'http://localhost:4200');
        return $response;
    }
}
  1. 修改security.yaml中的check_path指向自定义控制器:
firewalls:            
    login:
        pattern:  ^/api/login
        stateless: true
        json_login:
            check_path: app_custom_login_check # 替换为自定义控制器的路由名称
            success_handler: lexik_jwt_authentication.handler.authentication_success
            failure_handler: lexik_jwt_authentication.handler.authentication_failure
        http_basic: ~
  1. 在routes.yaml中添加路由:
app_custom_login_check:
    path: /api/login_check
    methods: [POST]
    controller: App\Controller\CustomLoginCheckController

三、使用NelmioCorsBundle(便捷的CORS管理)

若项目允许安装第三方bundle,NelmioCorsBundle可灵活配置CORS规则:

  1. 安装bundle:
composer require nelmio/cors-bundle
  1. 配置config/packages/nelmio_cors.yaml:
nelmio_cors:
    defaults:
        origin_regex: true
        allow_origin: ['http://localhost:4200']
        allow_methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']
        allow_headers: ['Content-Type', 'Authorization']
        expose_headers: ['Authorization']
        max_age: 3600
    paths:
        '^/api/':
            allow_origin: ['http://localhost:4200']
            allow_methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']
            allow_headers: ['Content-Type', 'Authorization']
            max_age: 3600

配置后会自动为所有/api前缀的接口添加正确的CORS响应头,包括/api/login_check。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 06:25:00