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内核事件监听给所有响应添加指定头:
- 创建事件监听器类
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控制器
若只想针对该接口单独处理,可自定义控制器替代默认逻辑:
- 创建自定义控制器
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; } }
- 修改
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: ~
- 在
routes.yaml中添加路由:
app_custom_login_check: path: /api/login_check methods: [POST] controller: App\Controller\CustomLoginCheckController
三、使用NelmioCorsBundle(便捷的CORS管理)
若项目允许安装第三方bundle,NelmioCorsBundle可灵活配置CORS规则:
- 安装bundle:
composer require nelmio/cors-bundle
- 配置
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
相关产品推荐
相关产品推荐

