1

いくつかの MVC アプリケーションで、トークン キーを使用して CSRF を防止しているのを見てきました。これが使用される典型的な例は、投稿の削除メソッドです。

また、GET メソッドと POST メソッドの両方を使用する実装を見てきました。

トークンを使用した GET リクエスト リンクの例:

https://domain.com/posts/G7j/delete/EOwFwC4TIIydMVUHMXZZdkbUR0cluRSkFzecQy3m5pMTYVXRkcFIBWUZYLNUNSNgQKdnpTWu

トークンを使用した POST リクエストの例:

<form action="/posts/G7j/delete" method="post">
    <input type="hidden" name="token" value="EOwFwC4TIIydMVUHMXZZdkbUR0cluRSkFzecQy3m5pMTYVXRkcFIBWUZYLNUNSNgQKdnpTWu" />
    <button type="submit">Delete</button>
</form>

ドキュメントに基づいて、これをCakePHPアプリケーションに実装することを検討しています: http://book.cakephp.org/2.0/en/core-libraries/components/security-component.html

ドキュメントによると、セキュリティ コンポーネントを追加すると、フォーム ヘルパーを使用するすべてのフォームにフォーム キーが自動的に追加されます。

例えば

public $components = array(
    'Security' => array(
        'csrfExpires' => '+1 hour'
    )
);

ただし、いくつか質問があります。

1.) 削除などの一部のアクションに POST over GET を使用するのはなぜですか? コントローラーのリクエストは、ユーザーが認証されているかどうか、権限を持っているかどうか、正しいフォームキーを持っているかどうかを確認します。

2.) CakePHP の GET リクエストでセキュリティ コンポーネントを使用するにはどうすればよいですか? ルーティングも処理する必要があると思います。

4

3 に答える 3

3

まず、CakePHP は追加レベルのセキュリティとして投稿リンクを使用して削除します。たとえば、認証システムが 100% 安全ではなく、ユーザーが手動で URL を入力して削除メソッドにアクセスできるとします。 /10 、ご想像のとおり、サーバー上のユーザーを実際に削除できますが、これは危険です。

二次的に GET リクエストをキャッシュまたはブックマークできるため、これらのリンクをブックマークしたユーザーは最終的に壊れたリンクに移動する可能性があり、これは決して良いことではありません。また、機密データが URL に表示されるため、たとえば誰かが GET 変数を使用してログイン ページをブックマークすると、無傷 - これにより、セキュリティが損なわれる可能性があります。

最後に、次のコードを使用して独自のトークンを簡単に生成できます。

$string = Security::hash('string', 'sha1 or md5', true);
print $this->Html->link("Link to somewhere",array("controller"=>"users","action"=>"delete",$string));

上記では、コア構成ファイルでソルト キーの設定を使用しますが、true をカスタム ソルトに置き換えることもできます。

于 2013-08-21T17:56:08.047 に答える
1

johhniedoeは、私が質問で尋ねたことと同様のことをどのように行っているかの例として、Croogo 1.3 を指摘してくれました。1.3 は 2.x より前の CakePHP を対象としていたため、コードが少し古くなったため、次のように修正しました。

最初に、セキュリティ コンポーネントが使用する CSRF トークンを というパラメータとして渡して、リンク (この場合は削除リンク) を作成しますtoken

<?php echo $this->Html->link('Delete', array('action'=>'delete','token'=>$this->params['_Token']['key'])); ?>

次に、トークンを処理するためのワイルドカード ルート接続を作成しました (通常、これは必須ではありませんが、NAMED トークンを使用しておらず、URL をクリーンに保ちたかったためです)。

Router::connect('/:controller/:action/:token', 
        array('controller' => 'action'),
        array(
            'pass' => array('token')
        )
    );

そして最後に、次のようにメソッドで処理します。

public function delete(){

    if (!isset($this->params['token']) || ($this->params['token'] != $this->params['_Token']['key'])) {
        $this->Security->blackHoleCallback = '__blackhole';
    } else {
        // do delete
    }
}

これは基本的に、トークンが一致しない場合は__blackhole、AppController で定義したブラックホール コールバック関数を使用してエラーを表示することを示しています。

ただし、最後に 1 つ注意しなければならないのは、トークンが複数回使用され、たとえば 1 時間続くことを許可する必要があるということです。これは、トークンがリセットされ、GET 要求が送信された後に一致しなくなるためです。

public $components = array(
    'Security' => array(
        'csrfExpires' => '+1 hour',
        'csrfUseOnce' => false
    )
);
于 2013-08-27T13:00:45.583 に答える