2021年3月

pug(jade)とは何か調べてみました。

HTMLの書き方に似たpug(Jade)を使用したので、いろいろ調べてみました。

pug(Jade)とは

pug(Jade)は、JavaScriptのテンプレートエンジンで、テンプレートと文字列とプログラムを組み合わせて出力ができます。元々はJadeという名前でしたが(拡張子は.jade)、2016年頃にpug(拡張子.pug)がリリースされたようです。

pugのインストール方法

pugを使用するには、Node.jsが必要になるので、下記の記事からNode.jsをインストールしてください。
※macでのインストール方法になります。

Node.jsのインストール方法

ますは、下記コマンドでnpmがインストールされているか確認

npm -v

バージョンが確認できればOKです。
pugをインストール

npm install pug-cli -g

インストールできているか確認

pug --version

pugの良さ

以下にpugを使用することのメリットを4点まとめました。

1. 閉じタグが不要
2. 変数が使用できる
3. 繰り返しが簡単
4. 条件分岐が使用できる

1. 閉じタグが不要

閉じタグを忘れてしまう、そもそもどこを閉じていないか探すことが無くなります。
タグの後に、半角スペースを忘れないようにしましょう。

■HTML

<!DOCTYPE html>
<html>
    <head>
        <title>タイトル</title>
    </head>
    <body>
        <h1>こんにちわ</h1>
        <p>hoge1</p>
        <ul>
            <li>hoge2</li>
            <li>hoge2</li>
        </ul>
    </body>
</html>

■pug

doctype html
html
    head
        title タイトル
    body
        h1 こんにちわ
        p hoge1
        ul
            li hoge2
            li hoge2

2. 変数が使用できる

共通で使用されている文言等を修正する場合、修正漏れがあったり、ひとつひとつ修正していくのは面倒です。
pugだと変数一箇所の修正で済みます。

■HTML

<!DOCTYPE html>
    <html lang="ja">
        <head>
        <meta charset="UTF-8">
        <title>変数の使用</title>
    </head>
    <body>
    ...

■pug

- var title = '変数の使用';
doctype html
html(lang="ja")
    head
        meta(charset="UTF-8")
        title #{title}
    body
    ...

3. 繰り返しが簡単

<li>を何個も書かなくても良いので、効率よく書けます。

■HTML

<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
</ul>

■pug

//- 改行&インデントすれば1個で済む
-
    ul
        each val in [1, 2, 3]
        li= val

さらに、連想配列も書けます。

■pug

-
    var arr = [
        {
            name : 'taro',
            age : 85,
        },
        {
            name : 'hanako',
            age : 55,
        }
    ];
ul
    each val in arr
        li #{val.name}:#{val.age}

4. 条件分岐が使用できる

最初にお話しましたテンプレートと文字列とプログラムを組み合わせて出力ができるとはどういうことか、
上記の繰り返しと条件分岐あたりで実感ができます。

// if文
- var name = 'taro'
if name=='hanako'
    p 花子です。
else if name=='taro'
    p 太郎です。
else
    p 存じ上げません。

// switch文
- var name = 'taro'
case name
    when 'hanako'
        p 花子です。
        - break
    when 'taro'
        p 太郎です。
    default
        p 存じ上げません。


まとめ

ソースが見やすくなり、文言の修正などは変数を使用するなどして、HTMLを効率良く書けることがpugの特徴だなと思いました。includeやextendsなども使えるようなので、いろいろ試してみたいと思います。

2016/09/19

「OWASP ZAP」で脆弱性診断を行ってみた

直近「OWASP ZAP」によるセキュリティ診断結果を目にする機会がありました。
OWASP ZAP」とはオープンソースで提供されているWebアプリケーション用の脆弱性診断ツールです。
こちら、診断結果をどのように出力しているのか気になったので、ローカルの仮想環境に作ったWebアプリケーションに対して軽く診断をしてみました。
実際に試してみたところ導入から診断まで、思ったより容易に行うことができたので、その流れについて簡単に記しておきたいと思います。
※本記事ではWindows10に「OWASP ZAP」をインストールして診断をしております

1. 診断対象の構成

仮想環境はWindows10 + Vagrant + VirtualBox で構築しています。
今回、仮想環境に作成したWebアプリケーションに対して脆弱性診断を行ってみます。
構成は以下となります。
 CentOS8
 php7.4
 mysql8.0
 nginx1.16.1 + php-fpm
 Codeigniter4

2. 「OWASP ZAP」 をインストール

以下よりインストールを進めます(標準インストール)
Download ZAP
(執筆時点ではver2_10_0でした)

javaがインストールさせれていない場合はインストールします。
Download Java
(執筆時点ではJRE1.8以上が必要でした)

インストール後、「OWASP ZAP」を起動すると以下が表示されます。

セッション保持については何を選んでも問題ありません。今回は「継続的に保存せず~」を選択します。
※セッションの保存先はデフォルトで
 ユーザーディレクトリ/OWASP ZAP/sessions
直下に作成されます

また、「OWASP ZAP」は推奨ブラウザをFirefoxとしているので、インストールしていない場合はインストールします。
Download Firefox

これでインストールは完了です。

3. 「OWASP ZAP」側の設定

OWASP ZAP」起動後まずは、意図しない診断対象に対してのスキャンをしないように、モードを「プロテクトモード」に変更しておきましょう。

次にポートの設定を行います。
「ツール」>「オプション」から「ローカル・プロキシ」を選択し、
 Adress:localhost
 ポート:11111
と入力します(ポート番号は被らない番号を入力しておきます)

更にポート設定後、SSL証明書の発行を行います。
「ツール」>「オプション」から「ダイナミックSSL証明書」を選択し証明書を保存しておきます(後続のブラウザ側の設定で使用します)

これで「OWASP ZAP」側の準備は完了です。

4. 「FireFox」側の設定

OWASP ZAP」側の設定が完了したら、FireFoxの設定を行います。
オプション>「一般」(左メニュー)>ネットワーク設定の「接続設定」を選択し、
前項『「OWASP ZAP」側の設定』で指定したHttpプロキシとポートを入力します。

続けて、前項『OWASP ZAP」側の設定』で保存した証明書をインポートします。
オプション>「プライバシーとセキュリティ」左メニュー>「証明書を表示」を選択し、「認証局証明書」タブを選択してインポートしましょう。

これで「FireFox」側の準備は完了です。

5. 診断を行う(動的スキャン)

上記設定が完了したら、「FireFox」で診断したいWebアプリケーションにアクセスします。
すると「OWASP ZAP」左メニューの「サイト」項目にアクセス情報が追加されていきます。
診断したいページにアクセスしていきましょう。
※本記事ではローカル環境`http://192.168.35.10/`各ページにアクセスしています。

アクセスが完了したら、「サイト」項目のURL(本記事では`http://192.168.35.10/`)を右クリック>「コンテキストに含める」>「New Context」を選択します。
サイト配下全てを対象とするため「対象のサイト/.*」に変更してOKを押下します。

コンテキストに対象のサイトが追加される(本記事では`http://192.168.35.10`)ので、右クリック>「動的スキャン」>「スキャンを開始」を押下します。
そうすると、以下のようにスキャンが開始されるので、気長に待ちましょう。

スキャンが100%になった後、ツールバーの「レポート」から診断結果を出力します。
※今回はHtmlで出力します。

上記のように出力され、4段階で脆弱性を診断してくれます。この診断結果をもとに脆弱性対策を進めます。
SolutionやReferenceの出力内容が参考になるでしょう。
例えば、Mediumの「X-Frame-Options Header Not Set」についてはNginx設定追加/変更をしながら対応をします。

▼hoge.conf 設定追加例

server {
    ...
    add_header X-Frame-Options SAMEORIGIN always;
    ...
}

診断結果をもとにNginx設定追加/変更行い再診断。MediumおよびLow項目がだいぶ減りました。修正/診断を繰り返し対処すべき警告がなくなるまで繰り返します。

6. まとめ

OWASP ZAP」によるセキュリティ診断結果を初めて見た際は、「脆弱性診断導入の敷居が高そう」といった印象でした。
ですが、今回簡単ではありますがインストール・診断まで実行してみて、『比較的容易に脆弱性診断が行える』ということがわかりました。また併せて、NginxやApacheに対しての設定の甘さに気づかされたので、今後診断結果で警告のあった項目については特に留意しておきたいと思います。


2016/09/19

Ajaxで外部APIを叩いてみたい

郵便番号から住所を取得できるWebサービス、ZipCloudの「郵便番号検索API」を使用し、
郵便番号検索で住所がフォームに自動入力される機能を作成してみましたのでご紹介させていただきます。
(こちらは練習用で作成しております。)

完成したものがこちら

郵便番号を入力して、検索ボタンを押すと住所が自動で入力されます。

使用API

ZipCloud「郵便番号検索API」:http://zipcloud.ibsnet.co.jp/doc/api
ご使用される場合は、利用規約のご確認をお願いします。)

ベースとなるURLはこちらです。

https://zipcloud.ibsnet.co.jp/api/search

郵便番号「2310023」で検索したい場合は、「zipcode=2310023」のようにURLにパラメータを付与します。

https://zip-cloud.appspot.com/api/search?zipcode=2310023

上記のURLにアクセスすると以下の結果が返却されます。

{
  "message": null,
  "results": [
    {
      "address1": "神奈川県",
      "address2": "横浜市中区",
      "address3": "山下町",
      "kana1": "カナガワケン",
      "kana2": "ヨコハマシナカク",
      "kana3": "ヤマシタチョウ",
      "prefcode": "14",
      "zipcode": "2310023"
    }
  ],
  "status": 200
}

Ajax通信を使用し、この返却される情報をもとに住所がフォームに自動入力される住所検索フォームを作成していきます。

・api.html

(※ "style.css" ファイルを読み込んでおりますが、今回 "style.css" ファイル内の内容は省略させていただきます。)

<!DOCTYPE html>

<html lang="ja">

<head>

  <meta charset="UTF-8">

  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <link rel="stylesheet" href="style.css">

  <!-- jQueryの読み込み  -->

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

  <!-- jsファイルの読み込み  -->

  <script src="api.js"></script>

  <title>郵便番号で住所検索</title>

</head>

<body>

  <h1>郵便番号で住所検索</h1>

  <div class="form-item">

    <label class="form-label">郵便番号</label>

    <input type="text" id="zipcode" maxlength="8" placeholder="例)1112222">

  </div>

  <button id="btn">検索</button>

  <h2>検索結果</h2>

  <div class="form-item">

    <label class="form-label">都道府県</label>

    <input type="text" id="prefecture">

  </div>

  <div class="form-item">

    <label class="form-label">市区町村</label>

    <input type="text" id="municipality">

  </div>

    <div class="form-item">

    <label class="form-label">住所</label>

    <input type="text" id="address">

  </div>

</body>

</html>

・api.js

$(function(){

    $("#btn").on('click', function () {

      // ajax通信開始

      $.ajax({

        url: "http://zipcloud.ibsnet.co.jp/api/search?zipcode=" + $('#zipcode').val(),

        // 現在のドメインと、データ取得先のドメインが異なるため 'jsonp' を指定

        dataType: 'jsonp',

      }).then(

        // 通信成功時の処理

        function (data) {

          if (data.results) {

            // 住所情報を取得

            var result = data.results[0];

            // フォーム入力欄の「都道府県」「市区町村」「住所」に値をセット

            $('#prefecture').val(result.address1);

            $('#municipality').val(result.address2);

            $('#address').val(result.address3);

          } else {

            alert('住所が見つかりません');

          }

        },

        // 通信失敗時の処理

        function () {

          alert("読み込み失敗");

      });

    });

  });


$.ajax({

        url: "http://zipcloud.ibsnet.co.jp/api/search?zipcode=" + $('#zipcode').val(),

        // 現在のドメインと、データ取得先のドメインが異なるため 'jsonp' を指定

        dataType: 'jsonp',

      }) ...

url:リクエスト先のURLを指定します。「$(‘#zipcode').val()」で入力された郵便番号を取得し、URLにパラメータを追加しています。

dataType:読み込むデータの種類を指定します。今回は、jsonpを使用しました。jsonpについての参考記事)

.then(

        // 通信成功時の処理

        function (data) {

          if (data.results) {

            // 住所情報を取得

            var result = data.results[0];

            // フォーム入力欄の「都道府県」「市区町村」「住所」に値をセット

            $('#prefecture').val(result.address1);

            $('#municipality').val(result.address2);

            $('#address').val(result.address3);

          } ...

Ajax通信が成功した場合、.then(function( )) の第一引数(今回の場合はdata)に取得したデータが入ってきます。
冒頭で郵便番号検索APIから返却された results 内に住所情報が入っていることを確認しました。
それぞれの値を住所検索フォームの各valueに設定し、完了です。

まとめ

以上、Ajax通信と、郵便番号検索APIを用いた住所を自動入力させる方法でした!

今回の練習で、APIからAjaxでデータ取得するまでの一連の流れを理解することができました。
ZipCloudなどの外部APIを使用すれば手軽に練習することができますね。

Ajax通信の部分では、JSONデータはクロスドメイン制限がある
(異なるドメインのサーバからデータを取得することができない)
ということも勉強になりました。

今後の実務に生かしていきたいです。

2016/09/19
1