作 ▸
Express 特定のパス以下でのみ認証が必要なWebAPIのサンプル
適当にライブラリとか使おうとしたら、そもそもミドルウェアとかルーティングとか全然分かってなくてダメだったので、勉強しました
Node.js v10.15.3express 4.17.1
以下のようなサンプルを作りました
- ポート 8080 で待ち受ける
- レスポンスはJSON文字列
- GET
/api/current
は認証なしで、現在のタイムスタンプを返す - GET
/api/auth/user
は認証ありで、認証されてるユーザー情報を返す - 認証がダメならステータスコード401を返す
認証と言ってもここではヘッダ x-api-key
の値が abc
であるかチェックしてるだけだし、ユーザー情報もただの固定値です
必要なものインストール
npm install express body-parser
ソースコード
無理やり1つのファイルに収めてます
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const port = process.env.PORT || 8080;
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
// /api 以下アクセス時のルーター
const apiRouter = express.Router();
/**
* GET /api/current
* 現在のタイムスタンプを取得
*/
apiRouter.get('/current', function(req, res) {
res.json({ current: (new Date()).getTime() });
});
// /api/auth 以下アクセス時のルーター
const closedApiRouter = express.Router();
/**
* GET /api/auth/user
* ログイン中のユーザー情報を取得
*/
closedApiRouter.get('/user', function(req, res) {
res.json({ user: res.locals.user });
});
/**
* 認証情報を検証するミドルウェア
*/
const authChecker = function(req, res, next) {
// これはただのサンプルなのでリクエストヘッダの x-api-key == abc なら認証OKとする
const apiKey = req.headers['x-api-key'];
if (apiKey != 'abc') {
// 認証NG
res.status(401).json({ message: 'dame-' });
} else {
// 認証OK、レスポンスのローカル変数にユーザー情報を追加
res.locals.user = {
id: 111,
name: 'kiriukun'
};
next(); // 次へ
}
};
// /api 以下アクセス時は apiRouter に行くように
app.use('/api', apiRouter);
// /api/auth 以下アクセス時は authChecker を通ってから closedApiRouter に行くように
apiRouter.use('/auth', authChecker);
apiRouter.use('/auth', closedApiRouter);
// エラーハンドラ
app.use(function(err, req, res, next) {
res.status(500).json({ error: err });
});
app.listen(port);
console.log('Listening on port ' + port);
動かしてみる
以下コマンドで起動します
node app.js
curlで叩いてみます
GET /api/current
curl -i http://localhost:8080/api/current
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 25
ETag: W/"19-L2BRp/mt8WwkDPT2isR4T7Gkygk"
Date: Mon, 21 Oct 2019 12:46:02 GMT
Connection: keep-alive
{"current":1571661962948}
GET /api/auth/user (x-api-keyが正しい)
curl -i -H "x-api-key: abc" http://localhost:8080/api/auth/user
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 37
ETag: W/"25-XOSwVlRNfVTdgRAWEbXKNWPByMw"
Date: Mon, 21 Oct 2019 13:40:45 GMT
Connection: keep-alive
{"user":{"id":111,"name":"kiriukun"}}
GET /api/auth/user (x-api-keyなし)
curl -i http://localhost:8080/api/auth/user
HTTP/1.1 401 Unauthorized
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 19
ETag: W/"13-scK9zgQpAQgMGcEigkbAl+qwPqE"
Date: Mon, 21 Oct 2019 13:41:21 GMT
Connection: keep-alive
{"message":"dame-"}
ちゃんと401でエラーになってます
備考
特定のパス以下とかじゃなくて、単純に特定のメソッドだけ認証したかったら、Router.get()
とかの第二引数にミドルウェアを渡せばいいらしい
/**
* GET /api/auth/user
* ログイン中のユーザー情報を取得
*/
closedApiRouter.get('/user', authChecker, function(req, res) {
res.json({ user: res.locals.user });
});
参考にさせていただいた記事など
サルでも分かるExpressでのjsonAPIサーバーの作り方 - Qiita
Express のレスポンス関連メソッド「res.end()」「res.send()」「res.json()」の違い - Corredor