W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
控制器過濾器可以是在控制器運行前或者運行后執(zhí)行相應(yīng)的操作,與 事件 不同,你可以非常簡單、方便的選擇在應(yīng)用程序的哪個 URI 上應(yīng)用過濾器。 過濾器可以修改傳入的請求,也可以對響應(yīng)做出修改,從而具有很大的靈活性和功能性。我們可以使用過濾器執(zhí)行一些共同的常見的任務(wù),例如:
過濾器類必須實現(xiàn) CodeIgniter\Filters\FilterInterface
接口。 過濾器類必須有 2 個方法:before()
和 after()
,它們會在控制器運行之前和之后執(zhí)行。 如果你的業(yè)務(wù)只需要其中一個方法,那另外的方法留空即可,不可以刪除。 一個標(biāo)準(zhǔn)的過濾器類模板如下:
<?php namespace App\Filters;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Filters\FilterInterface;
class MyFilter implements FilterInterface
{
public function before(RequestInterface $request)
{
// Do something here
}
//--------------------------------------------------------------------
public function after(RequestInterface $request, ResponseInterface $response)
{
// Do something here
}
}
任何過濾器,你都可以返回 $request
對象并且可以對當(dāng)前的請求進(jìn)行更改替換,這些更改在后續(xù)的控制器執(zhí)行時,仍然有效。
因為是前置過濾器,它會在控制器被執(zhí)行前觸發(fā),所以你有時會希望做一些驗證操作,不執(zhí)行后續(xù)的控制器,例如登錄驗證。那么你可以通過返回不是請求對象的任何形式來做到這一點。 通常是執(zhí)行重定向。 例如以下的示例:
public function before(RequestInterface $request)
{
$auth = service('auth');
if (! $auth->isLoggedIn())
{
return redirect('login');
}
}
如果返回了 Response
對象,那么 Response
對象會發(fā)送到客戶端,并且程序會停止運行。這對實現(xiàn) API 速率限制很有作用,詳細(xì)可以參考 app/Filters/Throttle.php 相關(guān)示例。
后置過濾器與前置過濾器幾乎一樣,不同的是后置過濾器只返回 $response
對象。并且,你無法停止程序的運行。你只能對 $response
對象 做一些修改,比如為了確??蛻舳丝梢哉WR別而設(shè)置某些安全選項,或者使用緩存輸出,甚至可以使用錯別字過濾器過濾最終的輸出內(nèi)容。
創(chuàng)建完過濾器后,你需要在 app/Config/Filters.php
配置它的運行時機(jī)。該文件包含了 4 個屬性,可以精確控制過濾器的運行時機(jī)。
$aliases
數(shù)組可以將一個簡單的名稱與一個或多個完整類的路徑進(jìn)行綁定關(guān)聯(lián),這些完整的類就是需要運行的過濾器:
public $aliases = [
'csrf' => \CodeIgniter\Filters\CSRF::class
];
別名是強(qiáng)制性的,如果你嘗試使用完整的類名,系統(tǒng)會觸發(fā)一個錯誤。以別名方式定義,可以很容易的切換實現(xiàn)類。例如當(dāng)你需要替換其他過濾器時,只需 要更改別名對應(yīng)的類即可。
當(dāng)然,你也可以將多個過濾器綁定到一個別名中,這樣可以使復(fù)雜的過濾器組變得簡單:
public $aliases = [
'apiPrep' => [
\App\Filters\Negotiate::class,
\App\Filters\ApiAuth::class
]
];
你可以在 $aliases
中定義多個別名以滿足系統(tǒng)需求。
這部分允許你定義應(yīng)用程序中每個請求需要經(jīng)過的過濾器。 請一定要注意過濾器的數(shù)量,因為所有的請求都將經(jīng)過這些過濾器,過多會導(dǎo)致影響性能。可以在 before
和 after
中添加別名來指定 過濾器:
public $globals = [
'before' => [
'csrf'
],
'after' => []
];
有時候你希望對絕大多數(shù)請求都使用過濾器處理,但個別請求需要單獨處理時,這樣的情況很常見。 一個常見的場景,你需要在CSRF預(yù)防過濾器中排除一些請求,例如來自第三方的請求或者特定的 URI 地址,其他請求則必須經(jīng)過 CSRF
驗證。 那么,我們可以通過 except
來實現(xiàn),可以定義一個或多個排除的 URI 地址:
public $globals = [
'before' => [
'csrf' => ['except' => 'api/*']
],
'after' => []
];
可以設(shè)置任意完整的 URI,也可以使用正則表達(dá)式,或者像本示例一樣,設(shè)置 星號* 通配符的形式來設(shè)置。這樣以 api/
開頭的所有請求都將不受 CSRF 過濾器的保護(hù)。但該應(yīng)用程序的其他請求不受影響。如果你需要指定多個 URI,可以使用數(shù)組的形式即可,具體可以參考示例:
public $globals = [
'before' => [
'csrf' => ['except' => ['foo/*', 'bar/*']]
],
'after' => []
];
你可以將過濾器應(yīng)用于請求的某些方法,例如 POST、GET、PUT等,在數(shù)組中使用全部小寫的形式指定過濾器名稱,與 $globals
或 $filters
屬性設(shè)置目的不同,這些過濾器全部都是前置過濾器,也就是說都在控制器運行前執(zhí)行:
public $methods = [
'post' => ['foo', 'bar'],
'get' => ['baz']
]
除標(biāo)準(zhǔn)的 HTTP 方法外,還支持兩種特殊的方法:’cli’ 和 ‘a(chǎn)jax’。它們是所有的 ‘cli’ 命令行運行的請求和 AJAX 請求。
注解
AJAX 請求的界定在X-Requested-With
標(biāo)志,在某些情況下,X-Requested-With
不會通過 JavaScript 的 XHR 請求發(fā)送到后端,從而導(dǎo)致過濾器無法執(zhí)行。如何避免此類問題,請參照文檔的 [AJAX 請求]() 章節(jié)。
這個屬性是過濾器別名數(shù)組,每個別名可以定義指定 URI 的前置或后置過濾器:
public filters = [
'foo' => ['before' => ['admin/*'], 'after' => ['users/*']],
'bar' => ['before' => ['api/*', 'admin/*']]
];
CodeIgniter4 默認(rèn)綁定了三個過濾器:Honeypot、Security 和 DebugToolbar。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: