處理第三方來的POST請求(Handling incoming third party POST requests)

Yii 預設會啟用 CSRF 保護,以驗證 POST請求是來自己方的程式。這是提昇安全性非常重要的環節。

不過,有時候我們也可能會暫時關閉這個保護,比方說需要允許其他程式透過 POST請求的時候。

另外,如果第三方透過 XMLHttpRequest (瀏覽器的 AJAX)存取資料,我們可能需要傳送符合跨來源資源共享(Cross-origin resource sharing,CORS)的標頭。

1. 怎麼作到

首先,永遠不要把 CSRF 保護整個取消。

如果CSRF會影響POST傳輸,僅僅針對單一控制器,甚至控制器的單一 action 取消就好。

1.1. 為特定控制器取消 CSRF

為特定控制器取消 CSRF 保護很簡單:

class MyController extends Controller
{
    public $enableCsrfValidation = false;

就這樣,我們加上一個公開參數 enableCsrfValidation,並將其設為false即可。

1.2. 為特定控制器 action 取消 CSRF

如果我們只想要對特定 action 取消,則稍微麻煩一點:

class MyController extends Controller
{
    public function beforeAction($action)
    {
        if (in_array($action->id, ['incoming'])) {
            $this->enableCsrfValidation = false;
        }
        return parent::beforeAction($action);
    }

這邊我們實做beforeAction()函式。 該函式會在整個 action 執行之前被呼叫。根據我們補充的程式,如果該函式的名字在我們的陣列裡面,則將 CSRF 保護關掉。注意在beforeAction()的最後,一定要return parent::beforeAction($action);

1.3. 送出 CORS 標頭

Yii 有一個自己的 Cors filter,幫助我們要允許 CORS 的時候,傳輸對應的標頭。

在整個控制器上面允許 AJAX requests,你需要:

class MyController extends Controller
{
    public function behaviors()
    {
        return [
            'corsFilter' => [
                'class' => \yii\filters\Cors::className(),
            ],
        ];
    }

如果只允許某個 action 的 AJAX requests,你需要:

class MyController extends Controller
{
    public function behaviors()
    {
        return [
            'corsFilter' => [
                'class' => \yii\filters\Cors::className(),
                'cors' => [],
                'actions' => [
                    'incoming' => [
                        'Origin' => ['*'],
                        'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
                        'Access-Control-Request-Headers' => ['*'],
                        'Access-Control-Allow-Credentials' => null,
                        'Access-Control-Max-Age' => 86400,
                        'Access-Control-Expose-Headers' => [],
                    ],
                ],
            ],
        ];
    }

results matching ""

    No results matching ""