안녕하세요. 명월입니다.
이 글은 CakePHP에서 CSRF token mismatch가 발생했을 때 처리하는 방법입니다.
PHP에서 Cake 프레임워크를 사용할때 Post Request를 보내면 발생하는 에러입니다.
이 에러는 routes.php를 보면 csrf 미들웨어를 등록되어 있는 것을 보실 수 있습니다.
사실 저 미들웨어 등록하는 부분을 주석처리하면 에러가 사라집니다. 정확히는 csrf 미들웨어를 사용하지 않는 형태로 되는 것입니다.
그럼 이 csrf 미들웨어가 무엇인지를 알아야 사용여부를 판단할 텐데, 이게 크로스-사이트 요청 위조 공격을 보호하는 미들웨어입니다.
다른 도메인에서 우리쪽 도메인으로 메소드는 POST로 form값을 넣고 점프하는 것을 막으려고 하는 것인데.. 이런 방식이 크게 도움이 되나 봅니다. 저는 개인적으로 잘 모르겠네요.. 결국 쿠기 가져가면 크로스-사이드 요청이 될 텐데 말입니다.
위 csrf 미들웨어를 등록 해제를 하지 않았다고 생각했을 때 사이트에 접속하면 csrfToken이라는 쿠키를 볼 수있습니다.
저 값을 POST의 form 데이터에 _csrfToken의 이름으로 포함시키면 저 에러가 발생하지 않습니다.
먼저 csrf 미들웨어를 사용한다고 생각한다면 저 쿠키값을 사용할 수 있게 view로 넘기기 전인 AppView에서 값을 설정합니다.
...
protected function _evaluate($viewFile, $dataForView) {
foreach ($dataForView as $key => $val) {
$this->_smarty->assign($key, $val);
}
$this->_smarty->assignByRef('this', $this);
if(@$dataForView["error"] !== null){
return parent::_evaluate($viewFile, $dataForView);
}
// request의 쿠키 값을 취득한다.
$_csrfToken = $this->getRequest()->getCookie("csrfToken");
// 그러나 페이지를 처음 방문시에는 쿠키가 설정이 되지 않으니 Set-Cookie의 해더값으로 데이터를 가져온다.
if($_csrfToken === null){
$_csrfToken = $this->getResponse()->getCookie("csrfToken")["value"];
}
// template에서는 _csrfToken로 사용한다.
$this->_smarty->assign("_csrfToken", $_csrfToken);
return $this->_smarty->fetch($viewFile);
}
...
그리고 폼 값안에 저 토큰 값을 넣으면 없어집니다.
<form method="post">
<input type="text" name="data">
<!-- 토큰을 넣는다. -->
<input type="hidden" name="_csrfToken" value="{$_csrfToken}"/>
<input type="submit">
</form>
CSRF token mismatch 에러가 사라졌습니다. 이 예제는 제가 form으로 submit했을 때 대응 방법이고 ajax에서 post타입일 경우도 아마 이 CSRF token mismatch가 나올 것입니다.
사실 이 때도 데이터에 _csrfToken값만 넣으면 해결됩니다.
<input type="text" id="data"><br />
<input type="text" id="data1">
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script>
$(function() {
$.ajax({
type: "POST",
url: "/Ajax/index",
dataType: "json",
success: function(msg) {
$("#data").val(msg.data);
$("#data1").val(msg.data1);
}
});
});
</script>
역시나 발생합니다. 이번에는 한개의 페이지가 아닌 레이아웃 페이지(default.ctp)로 가서 토큰 키를 넣겠습니다.
<!DOCTYPE html>
<html>
<head>
<title>Example</title>
</head>
<body>
<!-- 토큰키를 넣습니다. Dom의 id의 csrfToken입니다.-->
<input type="hidden" id="csrfToken" value="{$_csrfToken}" >
{$this->Flash->render()}
<div class="container clearfix">
{$this->fetch('content')}
</div>
<footer>
</footer>
</body>
</html>
그리고 다시 ajax가 있는 소스로 와서 저 토큰 키를 추가합시다.
<input type="text" id="data"><br />
<input type="text" id="data1">
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script>
$(function() {
$.ajax({
type: "POST",
url: "/Ajax/index",
// 토큰 키를 추가하도록 합시다.
data: {
"_csrfToken" : $("#csrfToken").val()
},
dataType: "json",
success: function(msg) {
$("#data").val(msg.data);
$("#data1").val(msg.data1);
}
});
});
</script>
Ajax도 제대로 데이터를 취득합니다.
여기까지 CakePHP에서 CSRF token mismatch가 발생했을 때 처리하는 방법 대한 글이었습니다.
궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.
'Development note > PHP' 카테고리의 다른 글
[PHP] ajaxForm을 이용한 파일 업로드(프로그래스바로 파일 업로드 상태를 표시하는 방법) (0) | 2019.10.26 |
---|---|
[PHP] String 객체를 다루는 방법 (EOT, ob_start, ob_get_contents, ob_end_clean, ob_end_flush) (0) | 2019.10.26 |
[PHP] PHPMailer 라이브러리를 이용해서 메일 발송하는 방법 (0) | 2019.10.19 |
[PHP] PHP의 HttpConnection 도구 cURL 사용 방법 (0) | 2019.10.18 |
[PHP] Apache 환경의 같은 호스트 안에서 PHP와 Java(Servlet)를 동시에 기동, 운영하는 방법 (0) | 2019.10.17 |
[PHP] 로그 라이브러리 Log4Php (0) | 2019.10.13 |
[PHP] 확장 DLL(Zend Extension dll) 파일을 작성하고 적용하는 방법(사용자 내장 함수 만들기) (0) | 2019.09.21 |
[PHP] xDebug 설치 방법 (0) | 2019.09.16 |