Skip to content

Commit

Permalink
Merge branch 'n1215-feature_csrf_protect'
Browse files Browse the repository at this point in the history
  • Loading branch information
sugumura committed Apr 22, 2016
2 parents c8d3075 + f5f7396 commit ba97965
Show file tree
Hide file tree
Showing 11 changed files with 114 additions and 4 deletions.
60 changes: 60 additions & 0 deletions auth/AntiCSRF.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php namespace Mizuderu\Auth;

class AntiCSRF {

/**
* @var string
*/
private $salt;

/**
* @var string
*/
private $algorithm;

/**
* .envの設定から作成
* @return AntiCSRF
*/
public static function fromEnv()
{
return new self(getenv('ANTI_CSRF_SALT'));
}

/**
* AntiCSRF constructor.
* @param string $salt
* @param string $algorithm
*/
public function __construct($salt, $algorithm = 'sha256')
{
if(!is_string($salt) || empty($salt)) {
throw new \InvalidArgumentException('saltは空でない文字列で指定してください。');
}

$this->salt = $salt;
$this->algorithm = $algorithm;
}

/**
* CSRF対策トークンを生成
* @return string
*/
public function generateToken() {
if (session_status() !== PHP_SESSION_ACTIVE) {
throw new \BadMethodCallException('セッションがアクティブではありません。');
}

return hash($this->algorithm, session_id() . $this->salt);
}

/**
* CSRF対策トークンの妥当性を検証
* @param string $token
* @return bool
*/
public function validate($token)
{
return $this->generateToken() === $token;
}
}
5 changes: 5 additions & 0 deletions bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,8 @@
)));

SessionManager::start();

// anti csrf protection
if(in_array($_SERVER['REQUEST_METHOD'], ['POST', 'PUT', 'DELETE', 'PATCH'])) {
validateCsrfTokenOrDie();
}
27 changes: 27 additions & 0 deletions config/helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,3 +165,30 @@ function callApi($method, $url, $data = false){

return json_decode($result, true);
}


require_once AUTH_DIR . '/AntiCSRF.php';
use Mizuderu\Auth\AntiCSRF;

/**
* CSRF対策トークンを生成
*
* @return string
*/
function csrfToken()
{
return AntiCSRF::fromEnv()->generateToken();
}

/**
* CSRF対策トークンを検証
* 不正ならステータスコード400でレスポンスを返す
*/
function validateCsrfTokenOrDie()
{
$token = filter_input(INPUT_POST, '_token');
if(!AntiCSRF::fromEnv()->validate($token)) {
header('Content-Type: text/plain; charset=UTF-8', true, 400);
die('不正なリクエストです。');
}
}
14 changes: 12 additions & 2 deletions config/template.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,20 @@ abstract public function render($template, $args);
*/
class TwigTemplate extends BaseTemplate
{
public function __construct()
/**
* コンストラクタ
* @param Twig_SimpleFunction[] $functions
*/
public function __construct(array $functions = [])
{
$this->template = new Twig_Environment(
new Twig_Loader_Filesystem(VIEW_DIR),
array('autoescape' => true)
);

foreach($functions as $func) {
$this->template->addFunction($func);
}
}

public function render($template, $args)
Expand All @@ -45,7 +53,9 @@ class Template
public static function factory()
{
if (is_null(self::$instance)) {
self::$instance = new TwigTemplate();
self::$instance = new TwigTemplate([
new Twig_SimpleFunction('csrfToken', 'csrfToken')
]);
}
return self::$instance;
}
Expand Down
1 change: 1 addition & 0 deletions views/delete.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
<h4>この情報を削除してもよろしいですか?</h4>
<br>
<form name='del' method='POST' action='delete.php'>
<input type=hidden name='_token' value='{{ csrfToken() }}'>
<input type=hidden name='post_time' value='{{ post_time }}'>
<input type=hidden name='del_flg' value='yes'>
<input type='submit' name='submit' value='削除'/>
Expand Down
1 change: 1 addition & 0 deletions views/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<meta name="keywords" content="熊本地震,給水,みずでる,水道">
<meta http-equiv="content-style-type" content="text/css">
<meta http-equiv="content-script-type" content="text/javascript">
<meta name="csrf-token" content="{{ csrfToken() }}">
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<link rel="stylesheet" href="css/owl.carousel.css">
<link rel="stylesheet" href="css/base.css">
Expand Down
1 change: 1 addition & 0 deletions views/news_post.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<body>
{% include "analyticstracking.html" %}
<form action="{{ php_self }}" method="POST" id="post" onsubmit="return confirm('送信してもいいですか?');">
<input type="hidden" name="_token" value="{{ csrfToken() }}">
<br>
<h2>ニュース</h2>
<div class="box">
Expand Down
1 change: 1 addition & 0 deletions views/post.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
水道から水が出ていますか?
</div>
<form action="{{ php_self }}" method="POST" id="post" onsubmit="return confirm('送信してもいいですか?');">
<input type="hidden" name="_token" value="{{ csrfToken() }}">
<input type="hidden" id="time" name="time" value="">
<input type="hidden" name="locate" id="locate" value="">

Expand Down
1 change: 1 addition & 0 deletions views/resolve.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
<h4>この情報を解決済みにしてもよろしいですか?</h4>
<br>
<form name='resolve' method='POST' action='resolve.php'>
<input type=hidden name='_token' value='{{ csrfToken() }}'>
<input type=hidden name='post_time' value='{{ post_time }}'>
<input type=hidden name='resolve_flg' value='yes'>
<input type='submit' name='submit' value='解決済みにする'/>
Expand Down
1 change: 1 addition & 0 deletions views/rousui_post.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
水漏れを報告してください
</div>
<form action="{{ php_self }}" enctype="multipart/form-data" method="POST" id="post" onsubmit="return confirm('送信してもいいですか?');">
<input type="hidden" name="_token" value="{{ csrfToken() }}">
<input type="hidden" id="time" name="time" value="">
<input type="hidden" name="locate" id="locate" value="">

Expand Down
6 changes: 4 additions & 2 deletions webroot/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var tools_height = document.getElementById('tools').clientHeight;
function attachMessage(marker, post_time, flg, comment, rousui_image_url, rousui_status) {
google.maps.event.addListener(marker, 'click', function (event) {

var csrf_token = $("meta[name='csrf-token']").attr("content");
var t = new Date(post_time * 1000);

var year = t.getFullYear();
Expand Down Expand Up @@ -43,7 +44,7 @@ function attachMessage(marker, post_time, flg, comment, rousui_image_url, rousui
var resolve_str = "";
// 漏水の画像があるなら表示
if(flg == "rousui" && rousui_status != 1){
resolve_str = "<br>" + "<a href='' onclick='document.resolve.submit();return false;'>解決済みにする</a>" + "<form name='resolve' method='POST' action='resolve.php'>" + "<input type=hidden name='post_time' value='" + post_time +"'> ";
resolve_str = "<br>" + "<a href='' onclick='document.resolve.submit();return false;'>解決済みにする</a>" + "<form name='resolve' method='POST' action='resolve.php'>" + "<input type=hidden name='_token' value='" + csrf_token +"'> " + "<input type=hidden name='post_time' value='" + post_time +"'> ";
}

var rousui_img = "";
Expand All @@ -56,7 +57,8 @@ function attachMessage(marker, post_time, flg, comment, rousui_image_url, rousui
var del_str = "";
//5分以内なら削除可能
if(flg != "rousui" && parseInt(now.getTime() / 1000) < (parseInt(post_time) + (60 * 5))){
del_str = "<br><br>" + "<a href='' onclick='document.del.submit();return false;'>この情報を削除する</a>" + "<form name='del' method='POST' action='delete.php'>" + "<input type=hidden name='post_time' value='" + post_time +"'> ";

del_str = "<br><br>" + "<a href='' onclick='document.del.submit();return false;'>この情報を削除する</a>" + "<form name='del' method='POST' action='delete.php'>" + "<input type=hidden name='_token' value='" + csrf_token +"'> " + "<input type=hidden name='post_time' value='" + post_time +"'> ";
}

new google.maps.Geocoder().geocode({
Expand Down

0 comments on commit ba97965

Please sign in to comment.