6
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

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

現時点で最新の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タグの部分を削除するなどいじってみると挙動が変わって面白いですよ!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
6
Help us understand the problem. What are the problem?