CSRF (cross site request forgery)特別對於表單的保護(尤其是登入頁面)很重要,在 Phalcon framework (3.x) 中可以參考以下範例(或者參考官方文件的 example)。
在登入頁面 (e.g. login.volt) 加上一個 hidden field,其 field name 與 field value 都是由 controller 產生給予。
<div class="container-fluid">
<div id="loginPanel">
{{ form("login/login", "method":"post", "autocomplete" : "off", "class" : "form-horizontal") }}
<input type="text" class="form-control" id="username" name="user[username]" placeholder="Username">
<input type="password" class="form-control" id="password" name="user[password]" placeholder="Password">
<input type="submit" class="btn btn-default" id="login" value="Log In">
<input type="hidden" name="{{csrfTokenKey}}" value="{{csrfToken}}">
{{ link_to('login/forget', "password forgot?") }}
</form>
</div>
</div>
然後在 controller 裏頭
<?php
class LoginController extends ControllerBase
{
public function indexAction()
{
// restart a session
$this->session->destroy();
$this->session->start();
// generate token for form forgery protection
$this->view->csrfTokenKey = $this->security->getTokenKey();
$this->view->csrfToken = $this->security->getToken();
}
public function loginAction()
{
if (!$this->request->isPost())
{
$this->flashSession->error("Should be a form post");
return $this->response->redirect("login/index");
}
// get the key of the last POST data element
end($_POST);
$key = key($_POST);
if (!$this->security->checkToken($key, $_POST[$key], false))
{
$this->flashSession->error("No form forgery");
return $this->response->redirect("login/index");
}
// do other things
// ...
}
}
比較要注意的是 security->getTokenKey() , security->getToken() , security->checkToken() 這三個 function call。官方文件在呼叫checkToke()時,是沒有傳任何參數,但實際上是等於拿 $_POST 資料的 tokenkey 跟 token 去做驗證 (如同上面的 sample code)。