5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

MojoliciousAdvent Calendar 2013

Day 7

4.59から導入されたCSRF対策を使ってみる

Posted at

現時点で最新のMojolicious「 4.59 」ではCSRF対策のメソッド諸々がようやく実装されました。以下Changesより引用。

  • Added CSRF protection support.
  • Added csrf_protect method to Mojolicious::Validator::Validation.
  • Added csrf_token attribute to Mojolicious::Validator::Validation.
  • Added csrf_token helper to Mojolicious::Plugin::DefaultHelpers.
  • Added csrf_field helper to Mojolicious::Plugin::TagHelpers.

Mojoliciousデフォルトのセッションを使うのでPlack::Middleware::Sesssionその他を使っている場合は有効にならないケースがありますが、カジュアルにCSRF対策をするにはよいでしょう。また内部のコードを追えば独自のCSRF-Protectionなヘルパーなどを自作するキッカケになるかもしれません。今回はMojolicious::Liteで試せるサンプルをつくってみました。

ポイントは..

  • テンプレートの中で csrf_token ヘルパーメソッドを呼び出してhidden-typeなフォームに入れる
  • ちなみにTagヘルパーを使う場合は csrf_field で一発
  • Mojolicious::Validator::Validationの csrf_protect メソッドでtokenのバリデーションを行う
  • セッション $self->session->{csrf_token} にtokenが収められているのでそれを参照して独自にチェックもアリ

って感じです。ではサンプルのコードをば。ちょいと冗長に書いてある部分あるっす。

前半のコード

#!/usr/bin/env perl
use Mojolicious::Lite;
use Mojolicious::Validator;
use Mojolicious::Validator::Validation;

get '/' => sub {
    my $self = shift;
    $self->render('index');
};

post '/post' => sub {
    my $self = shift;
    my $validation = $self->validation;
    my $messages;
    if ($validation->csrf_protect->has_error('csrf_token') ) {
        push @$messages, 'Invalid CSRF Token!';
    }
    if ($validation->required('text')->has_error('text') ) {
        push @$messages, 'Text is required!';
    }
    $self->stash->{messages} = $messages;
    $self->render('result');
};

app->start;

__DATA__
後半のコード

@@ index.html.ep
% layout 'default';
<form action="/post" method="post">
  <input type="text" name="text" placeholder="Text" />
  <input type="hidden" name="csrf_token" value="<%= csrf_token %>" />
  <input type="submit" value="Submit" />
</form>

@@ result.html.ep
% layout 'default';
% if ($messages) {
<b>Error!</b>
<ul>
% for my $message (@$messages) {
  <li><%= $message %></li>
% }
</ul>
% }else{
<b>Success!</b>
% }

@@ layouts/default.html.ep
<!DOCTYPE html>
<html>
  <head><title>How about CSRF?</title></head>
  <body><%= content %></body>
</html>

テンプレートのCSRF-tokenのinputタグの部分を削除するなどいじってみると挙動が変わって面白いですよ!

5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?