ThinkPHP6 - CORS 처리 종합 가이드

크로스 도메인

jq(JavaScript) 요청으로 인한 크로스 도메인(CORS) 문제를 해결하는 방법은 크게 3가지가 있습니다.

  1. 라우팅에서 체인 호출을 통해 특정 라우트 또는 라우트 그룹에 대해 크로스 도메인을 설정합니다. 예를 들어
Route::get('api/data', function() {
    return 'some data';
})->allowCrossDomain();

또는 프레임워크에 내장된 크로스 도메인 미들웨어를 활성화할 수 있습니다. 활성화 방법은 app\middleware.php 파일을 찾아 프레임워크에서 미리 정의된 미들웨어 클래스를 추가하는 것입니다.

<?php

// 전역 미들웨어 정의 파일
return [
    // \think\middleware\CheckRequestCache::class,
    // \think\middleware\LoadLangPack::class,
    // \think\middleware\SessionInit::class
    \think\middleware\AllowCrossDomain::class
];
  1. 다음과 같은 경우에는:
  • 사용자 정의 헤더를 사용하는 경우
  • 프론트엔드에서 응답 헤더를 처리해야 하는 경우

프레임워크에서 미리 정의된 미들웨어 소스 코드를 수정하거나, 사용자 정의 크로스 도메인 미들웨어를 만들어야 할 수 있습니다. 예를 들어, 프로젝트에서 X-API-Key 헤더를 사용하고, 프론트엔드에서 응답 헤더의 해당 필드 값을 로컬에 저장해야 하며, 소스 코드를 수정하고 싶지 않다면 다음과 같이 처리할 수 있습니다:

  • app\middleware\CustomCORSHandler.php 파일을 새로 생성하고, 프레임워크의 AllowCrossDomain을 상속받도록 합니다.
  • $customHeaders 속성을 오버라이드하여 필요에 따라 내용을 추가하거나 수정합니다.
<?php

namespace app\middleware;

use think\middleware\AllowCrossDomain;

class CustomCORSHandler extends AllowCrossDomain
{
    // 사용자 정의 요청 헤더 처리 추가
    protected $customHeaders = [
        'Access-Control-Allow-Credentials' => 'true',
        'Access-Control-Max-Age'           => 1800,
        'Access-Control-Allow-Methods'     => 'GET, POST, PATCH, PUT, DELETE, OPTIONS',
        'Access-Control-Allow-Headers'     => 'X-API-Key, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-CSRF-TOKEN, X-Requested-With',
        // 프레임워크가 응답 헤더를 가로챌 수 있으므로, 이 필드는 응답 헤더 출력을 허용하는 역할을 합니다.
        'Access-Control-Expose-Headers'    => 'X-API-Key'
    ];
}
  • app\middleware.php에서 CustomCORSHandler를 활성화합니다.
<?php

// 전역 미들웨어 정의 파일
return [
    // \think\middleware\CheckRequestCache::class,
    // \think\middleware\LoadLangPack::class,
    // \think\middleware\SessionInit::class
    // 사용자 정의 미들웨어 사용
    \app\middleware\CustomCORSHandler::class
];
  1. OPTIONS 요청 처리 방식 조정 이 단계에서도 일부 프론트엔드 요청은 여전히 크로스 도메인 문제를 일으킬 수 있습니다. 이는 OPTIONS 요청이 여전히 전체 실행 흐름을 거치기 때문일 수 있습니다. 따라서 public\index.phpOPTIONS 요청에 대한 인터셉트를 추가하여, 이후 어떤 미들웨어나 비즈니스 로직의 실행도 진입하지 않도록 하여 문제를 해결할 수 있습니다.
// [ 애플리케이션 진입 파일 ]
namespace think;

require __DIR__ . '/../vendor/autoload.php';

// OPTIONS 요청 처리
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    header('Access-Control-Allow-Credentials: true');
    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
    header('Access-Control-Allow-Headers: X-API-Key, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-CSRF-TOKEN, X-Requested-With');
    // 헤더를 실행한 후 즉시 종료
    exit;
}

// HTTP 애플리케이션 실행 및 응답
$http = (new App())->http;

$response = $http->run();

$response->send();

$http->end($response);

태그: ThinkPHP6 CORS PHP 미들웨어

6월 2일 00:11에 게시됨