👏

ONSEN GOODS開発記録 (番外編)

に公開

ミドルウェアとは何ぞや

「ONSEN GOODS」を開発していく中でいきなり出会った「ミドルウェア」という言葉。聞きなれない言葉だったので軽く調べたがいまいち分からなかったので、はじめはAIなどに導か何となく構築したりしていたが、ユーザー認証機能を追加していこうと思った矢先、急にミドルウェアに対しての知識を要求される場面が増えたため、「ONSEN GOODS」で記述した内容をもとにできるだけ理解を深めていこうと思う。

そもそもミドルウェアとは?

ミドルウェアとはざっくりいうとOSとアプリケーションの橋渡し役である。
ミドルウェアにはいろいろな役割があり、主に三つ

  • Webサーバー
    クライアントからのHTTPリクエストを最初に受け取り、静的コンテンツの配信や、動的なリクエストをアプリケーションサーバーに転送する役割。
  • アプリケーションサーバー
    Webサーバーから転送された動的なリクエストを受け取り、実際のビジネスロジック(ユーザー認証、データの取得・保存、など)を実行。
  • データベース管理システム(DBM)
    アプリケーションサーバーからのデータ要求(SQLクエリなど)を受け取り、データの保存、取得、更新、削除を行う。
    このあたりがよくつかわれる。

これらの役割を見ると今回のアプリで必要なものばかり、つまり一般的に一つのアプリに対して複数のミドルウェアが必要になるのが一般的ということ。

コードをもとに解説

CROS

今回のアプリでまず必要になったのはCROSというセキュリティ機能に関する公開ミドルウェア。
開発用の環境構築のために導入した。

server.js
const cors = require('cors'); //CORSミドルウェアを読み込む

app.use(cors()); // 全てのオリジンからのリクエストを許可(開発用)
app.use(express.json());

アプリケーションがサーバー側のAPIにアクセスする際、サーバーがフロント側と異なるポートで動作している場合、ブラウザのセキュリティによって異なるポートとの直接通信がブロックされるため、CROSによって特別に通信を許可している。
ただし、あくまで開発用であることに注意。

自分で定義した場合

ミドルウェアはまえのCROSなどのライブラリとして用意されているものもあれば、自分で新たに構築することもできる。

auth.js
const jwt = require('jsonwebtoken');

function authenticateJWT(req, res, next) {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.startsWith('Bearer') ? authHeader.split(' ')[1] : authHeader;

  if (!token) {
    return res.status(401).json({ message: 'トークンがありません。'});
  }
  jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
    if (err) {
      return res.status(403).json({ message: 'トークンが無効です。'});
    }
    req.user = user;
    next();
  });
}

module.exports = authenticateJWT;

これはユーザー認証に必要なミドルウェアであり、ユーザーのリクエストのヘッダーからトークンを取得してトークンが存在するか、トークンが有効かを検証するミドルウェア。
トークンの格納場所が少し特殊だったりするのでわかりずらいが、処理としてはあまり難しくはない。ようはトークンを検証するための関数である。

ミドルウェアはwebアプリケーションであればブラウザにもともとサナ割っているものも多く、開発者は知らず知らずのうちにその機能にあやかっていることも多い。あまり難しく「ミドルウェアとは何か?」などと考えずに、はじめのうちは「この機能が必要だからこれをもってこよう」、「これを定義しよう」くらいの感じて実装していけばいいと思う。

Discussion