컨트롤러 필터

컨트롤러 필터를 사용하면 컨트롤러 실행 전후에 작업을 수행할 수 있습니다. 이벤트와 달리 필터를 적용할 특정 URI를 선택할 수 있습니다. 수신(Incoming) 필터는 요청을 수정하는 반면 사후(after)필터는 응답에 대해 작동하고 데이터를 수정할 수 있기 때문에 많은 유연성과 성능을 제공합니다. 필터로 수행할 수있는 일반적인 예는 다음과 같습니다:

  • 수신 요청(request)에 대한 CSRF 보호

  • 역할(role)에 따른 사이트 영역 제한

  • 특정 엔드 포인트의 속도 제한

  • “유지 보수 또는 서버 점검” 페이지 표시

  • 자동 컨텐츠 협상(content negotiation)

  • and more..

필터 만들기

필터는 CodeIgniter\Filters\FilterInterface를 구현(implement)하는 간단한 클래스입니다. 두 개의 메소드 before()after()를 가지고 있으며, 컨트롤러 전후에 각각 실행됩니다. 클래스에는 두 메소드가 모두 포함되어야하지만 필요하지 않은 경우 메소드를 비워둘 수 있습니다. 스켈레톤 필터 클래스는 다음과 같습니다.

<?php

namespace App\Filters;

use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;

class MyFilter implements FilterInterface
{
    public function before(RequestInterface $request, $arguments = null)
    {
        // Do something here
    }

    public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
    {
        // Do something here
    }
}

사전(Before) 필터

모든 필터는 $request 오브젝트를 반환할 수 있으며, 컨트롤러가 실행될 때 변경 사항을 적용할 수 있도록 현재 요청(Request)을 대체합니다.

컨트롤러가 실행되기 전에 필터가 실행되기 때문에 먼저 컨트롤러의 작업을 중지하거나, 특정 필터 이후의 필터 실행을 중지할 필요가 있습니다. 비어 있지 않은 결과를 반환하면 쉽게 이 작업을 수행할 수 있습니다. 이전 필터가 빈 결과를 반환하면 컨트롤러 작업 또는 이후 필터가 계속 실행됩니다. Request 인스턴스의 경우는 비어 있지 않은 결과 규칙의 예외입니다. before 필터에서 반환하면 실행이 중지되지 않고 현재 $request 개체만 교체됩니다.

아래 예는 리디렉션을 수행합니다.

<?php

namespace App\Filters;

use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;

class MyFilter implements FilterInterface
{
    public function before(RequestInterface $request, $arguments = null)
    {
        $auth = service('auth');

        if (! $auth->isLoggedIn()) {
            return redirect()->to(site_url('login'));
        }
    }
}

응답(Response) 인스턴스가 리턴되면 응답이 클라이언트로 전송되고 컨트롤러 실행이 중지됩니다. API 요청에 대한 속도 제한을 구현하는데 유용하며, 이에 대한 예는 Throttler를 참조하십시오.

사후(After) 필터

사후(After) 필터는 $response 객체만 반환할 수 있으며, 컨트롤러 실행을 중지할 수 없다는 점을 제외하면 사전(After) 필터와 거의 동일합니다. 이를 통해 최종 출력을 수정하거나, 최종 출력으로 무언가를 수행할 수 있습니다. 이를 이용하여 특정 보안 헤더가 올바른 방식으로 설정되도록 하거나, 최종 출력을 캐시하거나, 나쁜(bad) 단어 필터로 최종 출력을 필터링하는 데 사용할 수 있습니다.

필터 구성

필터를 만든 후에는 실행시기를 구성해야 하며, 이 작업은 app/Config/Filters에서 이루어집니다. 이 파일에는 필터가 실행될 때 구성할 수 있는 네 가지 속성이 포함되어 있습니다.

Note

필터를 적용하는 가장 안전한 방법은 자동 라우팅 비활성화경로에 필터를 설정하는 것입니다.

Warning

필터 설정에서 URI 끝에 항상 *를 추가하는 것이 좋습니다. 컨트롤러 메서드는 생각보다 다른 URL에서 액세스하는 경우가 많기 때문입니다. 예를 들어, 자동 라우팅(레거시)가 활성화된 상태에서 Blog::index가 설정되어 있는 경우 blog, blog/index, blog/index/1등으로 액세스할 수 있습니다.

$aliases

$aliases 배열은 하나 이상의 정규화된 클래스 이름을 실행될 간단한 필터 이름으로 연결하는 데 사용합니다.

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class Filters extends BaseConfig
{
    public $aliases = [
        'csrf' => \CodeIgniter\Filters\CSRF::class,
    ];

    // ...
}

별명은 필수이며 이후 전체 클래스 이름을 사용하려고 하면 시스템에서 오류가 발생합니다. 이런 식으로 정의하면 필터에 사용되는 클래스를 간단하게 전환할 수 있습니다. 필터의 클래스만 변경하면 전환 완료되므로, 다른 인증 시스템으로 변경해야할 때 유용합니다.

여러 필터를 하나의 별칭으로 결합하여 복잡한 필터 세트를 간단하게 적용할 수 있습니다.

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class Filters extends BaseConfig
{
    public $aliases = [
        'apiPrep' => [
            \App\Filters\Negotiate::class,
            \App\Filters\ApiAuth::class,
        ],
    ];

    // ...
}

필요한만큼 별칭을 정의해야 합니다.

$globals

두 번째 섹션에서는 프레임워크의 모든 요청에 적용해야하는 필터를 정의할 수 있습니다. 모든 요청에 너무 많은 작업을 적용하는 것은 성능에 영향을 미칠 수 있으므로 여기에 얼마나 많은 것을 사용할지 주의해야 합니다. 사전(before) 또는 사후(after) 배열에 별칭을 추가하여 필터를 지정할 수 있습니다.

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class Filters extends BaseConfig
{
    public $globals = [
        'before' => [
            'csrf',
        ],
        'after' => [],
    ];

    // ...
}

모든 요청에 필터를 적용하고 싶을 때도 있지만, 몇 개만 남겨두어야 할 경우도 있습니다. 한 가지 일반적인 예는 CSRF 보호 필터에 몇 개의 URI를 제외하여 제3자 웹 사이트의 요청이 하나 또는 두 개의 특정 URI를 도달할 수 있도록 하고 나머지 URI는 보호해야 하는 경우입니다. 이렇게 하려면 ‘except’ 키가 있는 배열을 별칭 과 함께 값으로 일치시킬 URI를 추가하십시오.

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class Filters extends BaseConfig
{
    public $globals = [
        'before' => [
            'csrf' => ['except' => 'api/*'],
        ],
        'after' => [],
    ];

    // ...
}

필터 설정에서 URI를 사용할 수 있는 모든 장소, 정규 표현식을 사용하거나 이 예에서와 같이 와일드 카드 별표(*)를 사용하여 그 이후의 모든 문자를 일치시킬 수 있습니다. 다음 예는 api/로 시작하는 URL은 CSRF 보호에서 제외되지만 양식(Form)은 모두 보호됩니다. 여러 개의 URI를 지정해야 하는 경우 URI 패턴 배열을 사용할 수 있습니다.

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class Filters extends BaseConfig
{
    public $globals = [
        'before' => [
            'csrf' => ['except' => ['foo/*', 'bar/*']],
        ],
        'after' => [],
    ];

    // ...
}

$methods

POST, GET, PUT등과 같은 특정 HTTP 메소드의 모든 요청에 필터를 적용 할 수 있습니다. 이 배열에서는 메소드 이름을 소문자로 지정합니다. 값은 실행할 필터 배열입니다. $globals$filters 속성과 달리 이 속성은 이전(before) 필터처럼 실행됩니다.

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class Filters extends BaseConfig
{
    public $methods = [
        'post' => ['foo', 'bar'],
        'get'  => ['baz'],
    ];

    // ...
}

표준 HTTP 메소드 외에도 ‘cli’도 필터를 지원합니다. ‘cli’ 메소드는 명령줄에서 실행된 모든 요청에 적용됩니다.

Warning

$methods 필터를 사용하는 경우 Auto Routing (Legacy) 비활성화 해야 합니다. 예상하지 못한 방법으로 컨트롤러에 액세스하면 필터를 우회할 수 있습니다.

$filters

이 속성은 필터 별칭(alias)의 배열입니다. 각 별명(alias)에 대해 필터링해야 하는 URI 패턴 목록이 포함된 전후 배열을 지정할 수 있습니다.

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class Filters extends BaseConfig
{
    public $filters = [
        'foo' => ['before' => ['admin/*'], 'after' => ['users/*']],
        'bar' => ['before' => ['api/*', 'admin/*']],
    ];

    // ...
}

필터 인수(arguments)

라우터에 필터를 구성할 때 필터에 필요한 추가 인수를 전달할 수 있습니다.

<?php

$routes->add('users/delete/(:segment)', 'AdminController::index', ['filter' => 'admin-auth:dual,noreturn']);

이 예에서 ['dual', 'noreturn'] 배열은 필터의 before()after() 메소드에 $arguments로 전달됩니다.

필터 확인

spark routes 명령으로 경로와 필터를 볼 수 있습니다. URI 라우팅을 확인하세요.

제공되는 필터

CodeIgniter4에 3개의 필터가 번들로 제공됩니다: Honeypot, CSRF, InvalidChars, SecureHeaders, DebugToolbar

Note

필터는 구성 파일에 정의되어 선언된 순서대로 실행됩니다. 그러나 DebugToolbar를 활성화하면 다른 필터에서 발생하는 모든 것을 캡처해야 하므로 선언된 순서와 상관없이 항상 마지막에 실행됩니다.

InvalidChars

이 필터는 사용자 입력 데이터($_GET, $_POST, $_COOKIE, php://input)가 다음 문자를 포함하는 것을 금지합니다.

  • 잘못된 UTF-8 문자

  • 줄 바꿈 및 탭 코드를 제외한 제어 문자

SecureHeaders

이 필터는 프로그램의 보안을 강화하는 데 사용할 수 있는 HTTP 응답 헤더를 추가합니다.

헤더를 사용자 정의하려면 CodeIgniter\Filters\SecureHeaders를 확장하고 $headers 속성을 재정의한 후 app/Config/Filters.php에서 $aliases 속성을 변경합니다.

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class Filters extends BaseConfig
{
    public $aliases = [
        // ...
        'secureheaders' => \App\Filters\SecureHeaders::class,
    ];

    // ...
}

보안 헤더에 대해 알고 싶다면 OWASP Secure Headers Project를 살펴보십시오.