フレームワーク

Drupal 11 でルートとコントローラーを定義する

概要

画面を追加する場合は、ルーティング定義とコントローラーを分離します。アクセス権もルートで明示します。

実施例

example_tools.hello:
  path: '/example-tools/hello'
  defaults:
    _controller: '\Drupal\example_tools\Controller\HelloController::page'
    _title: 'Hello'
  requirements:
    _permission: 'access content'

注意点

画面ロジックにDB接続やグローバル関数を直接書かず、必要なサービスを依存性注入で受け取ります。

参考: 公式ドキュメント

続きを読む

Drupal 11 の最小カスタムモジュールを作る

結論

Drupal 11でモジュールとして認識させるために必須なのは、モジュール情報を定義する .info.yml です。hookは必須ではありません。独自ページを表示する場合は .routing.yml とControllerを追加し、Drupalの処理へ介入したい場合だけ必要なhookを実装します。

ここでは、公開ページ /pixie-hello と hook_help() を持つ、コピーして試せる最小構成を作ります。

前提

  • Drupal 11がComposer構成でインストール済みであること
  • Drupalのドキュメントルートが web であること。構成が異なる場合は、そのドキュメントルートへ読み替えること
  • Drushを vendor/bin/drush から実行できること

完成するディレクトリ構成

web/modules/custom/pixie_hello を作り、次の4ファイルを配置します。

続きを読む

Drupal は、ウェブ 2.0 時代のフレームワークだ。

Drupal とは何だろう? Drupal のコミュニティでコンセンサスが得られているものとしては、

    <li>コンテンツ管理システム(CMS)</li>
    <li>ウェブアプリケーションフレームワーク</li>
    <li>コミュニティ</li>
    

である。 最初の CMS については、疑いない。Drupal の入り口としては、私も Movable Type の再構築に辟易し、ブログの置き換えを狙っていた。要は簡単にサイトが作れるというものである。

続きを読む

AJAX で、動的にテーブルを作る方法(中・上級)

先のエントリーAJAX で、動的にテーブルを作る方法(初級)では、感じをつかむために、ベタにテーブルを作成していたため、重複するロジック/コードが多かった。ここではそれをフレームワークっぽくした。こういう軽量なコードを理解した上で、ひな型として自分で持っておくと見通しがよくてよいと思う。

この JavaScript ではできるだけ Java のアプレットにならった構造やメソッド名に近づけた。つまり、

続きを読む

ウェブサイト構築時のセキュリティのポイント

IPA(独立行政法人情報処理推進機構)の「安全なウェブサイトの作り方」というドキュメントは、なかなかまとまっていて、良い。すべてのウェブアプリ開発者は目を通しておくべきだ。ここではこのドキュメントから注意点をピックアップしてまとめてみた。

  1. SQL インジェクション
  2. OS コマンド・インジェクション
  3. パス名パラメータの未チェック/ディレクトリ・トラバーサル
  4. セッション・ハイジャック
  5. クロスサイト・スクリプティング
  6. クロスサイト・リクエスト・フォージェリ (CSRF)
  7. HTTP ヘッダ・インジェクション
  8. メールの第三者中継

続きを読む

Perl で、デーモン (Daemon) のプログラムを書くには?

Perl で、スクリプトをデーモン化するのはそんなに難しくない。Proc::Daemon というモジュールを使えば簡単にできるのだが、それには小さなフレームワークに沿ってスクリプトを書かねばならない。次のサンプルに空のフレームワークを示したので、既存のスクリプトがある場合にはこれに沿って自分のスクリプトを少々改造すればよい。基本的には action サブルーチンにロジックを書けばいいようになっている。

使用するモジュール


use Proc::Daemon;
続きを読む

パスワードは生のままデータベースに保存してはいけない?

いわゆるログイン処理において、ユーザーがウェブページのフォームから入力してきたユーザー名とパスワードをデータベースに保存されているものと照合し、認証するという仕組みはメンバー制サイトにはもはや欠かせないものとなっている。ここで、ユーザー名とパスワードは SSL で暗号化された通信路(チャネル)を通じてサーバに送るのは当然として、データベースにユーザー名とパスワードを生のまま入れていた場合は、もしデータベースが何者かにハッキングされたらパスワードがそのまま漏洩してしまうことになる。パスワードというものはある個人であればどのサイトでも共通にしていることも多いのではないだろうか? あなたはまさにこのエントリを読んでいるくらいなのだからそんなことはないかも知れないが、一般ユーザーのセキュリティに対するリテラシーはどうだろう?そのようなことを前提にすると、仮に(あってはならないことだが)自サイトからパスワードが漏れた場合、そのパスワードを使って悪意のあるものが次々に他のサイトへの認証を試みるシナリオもあると思う。また、データベースがハッキングされないまでも、管理者がデータベースを覗けばユーザーが設定したパスワードを簡単に見ることができるシステムは、やはりセキュリティ上問題であろう。

このような事態を避けるためにも、セキュリティの基本ではあるが、データベース中のパスワードはハッシュ文字列で保存しておくべきである。たとえデータベースの管理者がデータベースに保存されているハッシュ値を覗けたとしても、そのハッシュ値からのパスワード自体の復元はほぼ不可能だからだ。このような仕組みにすると、ユーザーがパスワードを忘れた場合はパスワードで照合できなくなるので、再設定の仕組みが必要である。このポイントを頭に入れて注意深く世のサイトがどのように作られているか、普段からアンテナをはって参考にして欲しい。

この方法は特に Perl だけにできるということではなく、もちろん言語を問わず、ハッシュ関数が用意されている Java や PHP にも使える。

続きを読む

Perl で、セッション管理をしたい。 (Apache::Session)

Apache::Session を使う。 パフォーマンスを少し測ってみたら CGI::Session よりも若干速いようである。

このモジュールは eval {...}; とセットで使うとよい。 - Perl で、例外処理をするような感じのもの。if($@) {...} のセットで使う。eval にはセミコロン(;) を忘れないこと。

例では、%session を $session としてハッシュで返している。
このモジールを使う利点は、ID の長さを自由に変えられることである。CGI::Session の場合は、ID の長さを変えたければ、自分で書かなければならない。一方で短所は、セッションの有効期限を設定できないこと。そのため、MySQL 中のsessions テーブルに timestamp フィールドを独自に追加して、自身の CGI の中か cron で適宜 reap する必要がある。また、セッションオブジェクト中の個別のデータにも有効期限を設けることはできない (CGI::Session はできる)。それでもこのモジュールが良いのは、パフォーマンスが CGI::Session よりも若干良いのと、ID の長さを変えられるからである。


use DBI;
use Apache::Session;

このモジュールは永続ストレージ (要はセッション情報をずっと溜めておけるデータベース) の種類によっていろいろな種類がある。


Apache::Session::MySQL
Apache::Session::Postgres
Apache::Session::File
Apache::Session::Oracle
Apache::Session::Sybase
Apache::Session::DB_File
Apache::Session::Flex 	実行時にすべてのパラメータを指定する

以下の例では Apache::Session::Flex を使っている。

use DBI; use Apache::Session::Flex; $session = _getSession; print $session->{_sessin_id} sub _getSession {
my $db;
my ($database, $username, $password);
# 以上の変数には値を入れること。

$db = DBI->connect("DBI:mysql:$databasename",
                             $username,
                             $password
                             ) || die 'Cannot connect db';
eval {
tie %session, 'Apache::Session::Flex', $sid, {

    Store      => 'MySQL',
    Lock       => 'MySQL',
    Generate   => 'MD5',
    IDLength   => 32,
    Serialize  => 'Storable',
    Handle     => $db,
    LockHandle => $db,
};
}; # セミコロンを忘れないこと if($@) { # $@: error message of eval
return undef;
} # セッション ID の取得に成功。ここに処理を書く。
return \%session;
}
続きを読む

Perl で、CGI::Application を使う

CGI::Application は HTML::Template を統合している。以下は HTML::Template のドキュメントで書かれている例が含まれている。

使用するモジュール


use CGI::Application;

# 要 HTML::Template
# IPC::SharedCache (こちらは任意)

まずは以下のようなディレクトリとファイル構成にする。


./cgi-bin/lib/App.pm
./cgi-bin/templates/test.templ
./cgi-bin/index.cgi

index.cgi の内容:
基本的に App クラスを new して app->run() としているだけである。
BEGIN ブロックのそれはライブラリへのパスを探している。

#!/usr/bin/perl -w use strict; my $LIB_DIR; BEGIN {
if ($0 =~ m!(.*[/¥¥])!) {
    $LIB_DIR = $1;
} else {
    $LIB_DIR = './';
}
unshift @INC, $LIB_DIR . 'lib';
} use App; my $app = App->new(); $app->run(); 1;

App.pm の内容。

  1. このモジュールでは、このモジュールから return で返した文字列が出力されるようになっている。よって例では、結果的に $template->output が返す文字列を App オブジェクトから返している。後は自動的に出力される。
  2. $self->mode_param('rm') とあるのはフォームやURL中のクエリ文字列で rm='次に実行すべきメソッド' を指定しろ、ということ。例えば <input type=hidden name=rm value=do_next> みたいな感じである。'rm' がキーワード、メソッド名が値となっている。
  3. $self->start_mode('start') は、見ての通り、このアプリケーションがスタートしたときに実行されるメソッドを指定する。
  4. teardown (=destory と同義) は終了時に呼ばれるメソッド。
  5. このモジュールは CGI、HTML::Template と統合されていて、HTTP ヘッダなども $self->header_props と、CGI と同じように呼び出せる。
  6. HTML::Template については、$self->load_tmpl で HTML::Template オブジェクト (実体はハッシュリファレンス) が取り出せるようになっている。このとき指定できるキャッシュパラメータで、cache、double_cache は Linux など OS の実行プラットフォームに IPC::SharedCache モジュールがインストールされてないと使えない。
#!/usr/bin/perl -w package App; use strict; use base 'CGI::Application'; sub setup {
my $self = shift;
$self->mode_param('rm');
$self->start_mode('start');
$self->run_modes(
        'start' => ¥&start,
        'end'   => ¥&end
    );
    $self->header_props(-type=>'text/html', -charset=>'utf-8');
} sub teardown {
my $self = shift;
# Post-response shutdown functions
# ここにはデータベースの切断を書くとよい。
} sub start {
my $self = shift;
my $template = $self->load_tmpl('test.tmpl',  die_on_bad_params => 0,
    path => ['......./cgi-bin/templates'],
# cache => 1, # double_cache => 1, # file_cache => 1, # file_cache_dir => '/tmp', # double_file_cache => 1
);
return &template($template);
} sub end { } sub template {
my $template = shift;

# the fruit data - the keys are the fruit names and the values are
# pairs of color and shape contained in anonymous arrays
my %fruit_data = (
                Apple  => ['Red, Green or Yellow', 'Round'      ],
                Orange => ['Orange'              , 'Round'      ],
                Pear   => ['Green or Red'        , 'Pear-Shaped'],
                Banana => ['Yellow'              , 'Curved'     ],
               );

my @loop;  # the loop data will be put in here

# fill in the loop, sorted by fruit name
foreach my $name (sort keys %fruit_data) {
    # get the color and shape from the data hash
    my ($color, $shape) = @{$fruit_data{$name}};

    # make a new row for this fruit - the keys are <TMPL_VAR> names
    # and the values are the values to fill in the template.
    my %row = ( 
           name  => $name,
           color => $color,
           shape => $shape
          );

    # put this row into the loop by reference             
    push(@loop, \%row);
}

# call param to fill in the loop with the loop data by reference.
$template->param(fruit_loop => \@loop);

# print the template
return $template->output;
} 1;

test.tmpl の内容:

<HEAD>
    <TITLE>Fruity Data</TITLE>
</HEAD>
<BODY>
    <H1>Fruity Data</H1>

    <TABLE BORDER=1>

        <TR>
            <TD><B>Fruit Name</B></TD>
            <TD><B>Color</B></TD>
            <TD><B>Shape</B></TD>
        </TR>

    <TMPL_LOOP NAME="fruit_loop">
        <TR>
            <TD><TMPL_VAR NAME="name"></TD>
            <TD><TMPL_VAR NAME="color"></TD>
            <TD><TMPL_VAR NAME="shape"></TD>
        </TR>
    </TMPL_LOOP>

    </TABLE>

</BODY>       
続きを読む
フレームワーク を購読