ルモーリン

パスワードチェック

投稿:2019-03-07

サイト管理者だけが呼び出せるAPIとしてパスワードでチェックしたい。 でもPerlのスクリプトから呼び出すのでクライアント証明書を用意するほどではない。

サイト自体がSSLなのでAPIに送るパスワードは平文のままでも暗号化されるので途中の傍受でもバレないけれど、 サイトにパスワードを保存しておいて単純比較は面白くないから、 PCでSHA3を使ってダイジェスト化したものをサイトに置き、 受け付けたパスワードのダイジェストと比較しよう。

元々、Mojoliciousにはフォームのバリデーター(入力チェック機能)があります。 パスワードそのものを受け取っても良いけれど自作のフィルターを通せる仕組みがあるので 「SHA3のダイジェスト」のフィルターをプラグインで用意します。 ファイル名はSha3Validate.pmです。

package Sha3Validate;
use Mojo::Base "Mojolicious::Plugin";

use Digest::SHA3;
use Mojo::Util qw / encode /;

sub register {
	my ($self, $app, $conf) = @_;

	$app->validator->add_filter(sha3_digest => sub {
		my ($v, $name, $value) = @_;
		return Digest::SHA3->new(512)->add(encode(utf8 => $value))->hexdigest;
	});
}

1;

アプリケーションのstartupにルーターの設定を追加します。 これでクライアントからURLを呼ぶとコントローラーが呼ばれます。

	# 更新通知
	# 記事を追加/変更後に呼んで更新情報を再収集
	$r->post("/api/updatenotify")->to("ApiUpdateNotify#index");

呼ばれるコントローラを作ります。 ファイル名はApiUpdateNotify.pmです。 コードの中の??????????はパソコンでパスワードのダイジェストを計算して直書きします。 メソッドPpUpdateNotify(記事更新をサーバーに通知)が目的のAPIです。

package Myapp::Controller::ApiUpdateNotify;
use Mojo::Base 'Mojolicious::Controller';

use constant DIGEST => "??????????";

# This action will render a template

sub index {
	my $self = shift;

	my $validator = $self->validation->required("password", "sha3_digest");
	if ($validator->is_valid && DIGEST eq $validator->output->{password}) {
		$self->PpUpdateNotify;
		$self->render(text => "update notify ok.");
	} else {
		$self->reply->not_found;
	}
}

1;

パソコンから呼び出すスクリプトです。 コードの中の??????????は平文のパスワードです。

	my $ua = LWP::UserAgent->new;
	my $res = $ua->post("https://www.lemorin.jp/api/updatenotify",
		[password => "??????????"],
	);
	if ($verbose) {
		say $res->status_line;
		say $res->content if $res->is_success;
	}