Node.js + Express + Redisを使った簡単なログイン機能の実装
Node.js の Express と docker で立ち上げた redis を使って簡単なログイン機能を実装する手順をメモしました。
構成
Node.js と Express で立ち上げた web アプリから docker で立ち上げた redis へセッション情報を保存する構成で作成します。
redis(レディス)
redis とは?
Redis(リモートディクショナリサーバー)とは、オープンソースで提供されている高速なメモリ内 Key-Value データストアです。 データベース、キャッシュ、メッセージブローカー、およびキューなどを用途として利用します。
公式サイト
環境
- Mac OS Big SUR 11.3.1
- yarn 1.22.10
- Node 14.15.3
- express 4.17.1
- express-session 1.17.2
- redis 3.1.2
ファイル操作で利用する Unix コマンドについて
基本的なディレクトリ作成やファイル操作は Unix コマンドを利用します。
Unix コマンドについて詳しくはこちらの記事を参考にしてください。
事前準備
Docker 環境が必要
事前準備として Docker が利用できる環境で実施します。Docker のインストール手順についてはこちらを参照ください。
Node.js 環境が必要
事前準備として Node.js が利用できる環境で実施します。
Node.js の環境の構築について詳しくはこちらの記事を参考にしてください。
yarn コマンドのインストール
事前準備として Yarn が利用できる環境で実施します。
Yarn コマンドのインストールについて詳しくはこちらの記事を参考にしてください。
TypeScript 環境で実施
事前準備として TypeScript が利用できる環境で実施します。
TypeScript の実行環境の構築について詳しくはこちらの記事を参考にしてください。
プロジェクトの作成
プロジェクトディレクトリを作成
~/login-sampleというプロジェクトディレクトリを作成します。
terminal$ mkdir ~/login-sample
プロジェクトディレクトリへ移動
作成した~/login-sample ディレクトリへ移動します。
terminal$ mkdir ~/login-sample
yarn を初期化をして package.json を作成
yarn でプロジェクトの初期化を行います。
npm で実施する方は必要に応じて変更してください。
terminal$ yarn init -y
yarn init v1.22.10
warning The yes flag has been set. This will automatically answer yes to all questions, which may have security implications.
success Saved package.json
✨ Done in 0.08s.
必要なパッケージのインストール
必要なパッケージ
experss と TypeScript のパッケージをインストールします。
- express
- express-session
- cookie-parser
- redis
- connect-redis
- @types/express
- @types/express-session
- @types/cookie-parser
- @types/redis
- @types/connect-redis
- typescript
- @types/node
- ts-node
express
Express フレームワークのモジュールです。
express-session
Express でセッションを扱えるようにするためのミドルウェアです。
cookie-parser
cookie を読み取るためのミドルウェアです。Express のミドルウェアへ設定して利用します。
redis
Redis のモジュールです。
connect-redis
express-session のセッション保存先に redis を扱えるようにするモジュールです。
パッケージのインストール
yarn addコマンドで必要パッケージをインストールします。
terminal$ yarn add express express-session cookie-parser redis connect-redis
開発に関連するパッケージのため -Dオプションを付与しています。
sql$ yarn add -D @types/express-session @types/cookie-parser @types/redis @types/connect-redis @types/express typescript @types/node
インストールしたパッケージを確認
package.json を開きインストールされたパッケージを確認します。
perl "devDependencies": {
"@types/connect-redis": "^0.0.16",
"@types/cookie-parser": "^1.4.2",
"@types/express": "^4.17.12",
"@types/express-session": "^1.17.3",
"@types/node": "^15.12.5",
"@types/redis": "^2.8.30",
"ts-node": "^10.0.0",
"typescript": "^4.3.4"
},
"dependencies": {
"connect-redis": "^6.0.0",
"cookie-parser": "^1.4.5",
"express": "^4.17.1",
"express-session": "^1.17.2",
"redis": "^3.1.2"
}
設定ファイルを作成
tsconfig.json を作成
プロジェクトルートへ tsconfig.json を作成します。
terminal$ vi tsconfig.json
tsconfig.json の設定例
tsconfig.json{
"compilerOptions": {
"target": "es2020",
"module": "commonjs",
"lib": [
"es2020"
],
"sourceMap": true,
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"moduleResolution": "node",
"baseUrl": "src",
"esModuleInterop": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": [
"src/**/*"
],
"exclude": [
"dist",
"node_modules"
],
"compileOnSave": false
}
ts-config のオプションはこちらの記事を参考にしてください
Redis の立ち上げ
アプリケーションから接続する必要があるため先に Redis を立ち上げます。
docker-compose.yml を利用して docker でサクッと立ち上げます。
docker-compose.yml を作成
プロジェクトのルートディレクトリへ docker-compose.yml を作成します。
terminal$ vi docker-compose.yml
redis の設定記述
redis の設定を記述します。
docker-compose.ymlversion: '3.5'
services:
redis:
image: 'redis'
ports:
- '6379:6379'
volumes:
- './data:/data'
データ永続化のための data ディレクトリ作成
プロジェクトルートへデータ永続化のための data ディレクトリを作成します。
terminal$ mkdir data
docker を立ち上げ
docker-compose upコマンドで redis を立ち上げます。
terminaldocker-compose up -d
// 中略
Status: Downloaded newer image for redis:latest
Creating login-sample_redis_1 ... done
docker の起動を確認
docker psコマンドで redis の起動を確認します。
bash$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
11387a81aa9b redis "docker-entrypoint.s…" About a minute ago Up 56 seconds 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp login-sample_redis_1
以上で redis の立ち上げは完了です。
アプリケーションの構築
ソースディレクトリの作成
プロジェクトルートへsrcディレクトリを作成します。
terminal$ mkdir src
アプリケーションのファイルを作成
作成したソースディレクトリへ index.ts を追加します。
terminal$ vi src/index.ts
アプリケーションの設定を追記
利用するモジュールをインポート
import 文で利用するモジュールをインポートします。
src/index.tsimport express from 'express';
import cookieParser from 'cookie-parser';
import session from 'express-session';
import redis from 'redis';
import connectRedis from 'connect-redis';
各種初期化を実施
Express の初期化
import した express を呼び出して express を初期化します。
src/index.tsconst app = express();
express-session の初期化
redis を使用するための設定です。 connect-redis へ express-session を渡します。
src/index.tsconst RedisStore = connectRedis(session);
Redis の初期化
import した express を呼び出して express を初期化します。
src/index.tsconst redisClient = redis.createClient({
host: 'localhost',
port: 6379,
prefix: 'sid:',
});
redisClient.unref();
redisClient.on('error', console.log);
connect-redisのversion4で一部書き方が変わっています。 connect-redis/migration-to-v4.md at master · tj/connect-redis
ミドルウェアの設定
cookie-parser
express のミドルウェアへ cookie-parser を設定します。
src/index.tsapp.use(cookieParser())
body-parser
express のミドルウェアへ body-parser を設定してpostデータを受け取れるようにします。
body-parserはexpressに内包されるように変更になりました。
src/index.tsapp.use(express.urlencoded());
session の設定
express のミドルウェアへ settion の設定を渡します。
src/index.tsapp.use(
session({
secret: 'secret_key',
resave: true,
saveUninitialized: true,
store: new RedisStore({ client: redisClient }),
cookie: {
httpOnly: true,
secure: false,
maxAge: 1000 * 60 * 30,
},
})
);
secret
セッション ID Cookie に署名するために使用される文字列です。
任意の値を指定します。
resave
要求中にセッションが変更されなかった場合でも、セッションをセッションストアに強制的に保存するかどうかの設定です。
デフォルトを使用することは推奨されなくなったため明示的に指定しています。
saveUninitialized
「初期化されていない」セッションを強制的にセッション・ストアに保存するかどうかの設定です。
デフォルトを使用することは推奨されなくなったため明示的に指定しています。
store
セッションストアインスタンスになります。
ここで redis を指定しています。
cookie
Cookie の設定用のオブジェクトになります。
オプションについて詳細はこちらをご確認ください。
expressjs/session: Simple session middleware for Express
型の拡張
express-sessionでuser_idを利用するため型ファイルを拡張します。
型の拡張用のディレクトリ追加
terminal$ mkdir -p src/@types
@types.express-session.d.tsを作成
@types.express-session.d.tsを作成します。
terminal$ vi src/@types/express-session.d.ts
型の定義を追加
src/@types/express-session.d.tsimport 'express-session';
declare module 'express-session' {
interface SessionData {
user_id: string;
}
}
ログインページの作成
ログインページを作成します。
ログインページの仕様
クライアント
- ユーザー ID を入力するための入力ボックスを作成
- 送信ボタンを作成
- 送信ボタンをクリックしたら post でユーザー ID を送信する
サーバー
- アクセス URL は
/login - GET ならページを表示
- POST ならデータを確認してユーザー ID が送られてきたらユーザー ID をセッションへ保存し'/'へリダイレクト
クライアントの処理
ソースディレクトリ内へhtmlファイルを作成します。
htmlを格納するディレクトリ
htmlを格納するディレクトリを作成します。
terminal$ mkdir src/html
login.htmlを作成
login.htmlを作成します。
css$ vi src/html/login.html
login.html
入力されたuser_idをポストするだけの簡易的なformを作成しています。
src/html/login.html<form action="/login" method="post">
<p>ユーザーID</p>
<input type="text" name="user_id" value="" />
<input type="submit" value="送信" />
</form>
サーバーの処理
GET時の処理
/loginへのgetのリクエストでhtmlを表示します。
src/index.tsapp.get(
'/login',
(req: express.Request, res: express.Response): void => {
// login.htmlファイルを表示
res.sendFile(`${__dirname}/html/login.html`);
}
);
POST時の処理
/loginへのPOSTでuser_idがあったらsessionへ保存してリダイレクトさせます。
src/index.tsapp.post(
'/login',
(req: express.Request, res: express.Response): void => {
const { user_id } = req.body;
if (user_id) {
req.session.user_id = user_id;
res.redirect('/');
}
}
);
トップページの作成
トップページを作成します。
トップページの仕様
クライアント
- ユーザー ID を表示
- ログアウトページのリンクを表示
サーバー
- セッションのユーザー ID が存在したらページを表示
- セッションのユーザー ID が存在しなかったらログインページへリダイレクト
index.tsへトップページの処理追加
/のGETでアクセスがあったらsessionのuser_idを確認。
なかったら/loginへリダイレクトし
あったらuser_idとlinkタグを出力
src/index.tsapp.get(
'/',
(req: express.Request, res: express.Response): void => {
const { user_id } = req.session;
if (!user_id) {
res.redirect('/login');
}
console.log(user_id);
res.send(
`ようこそ${user_id}さん<br><a href="/logout">ログアウト</a>`
);
}
);
ログアウト処理の作成
ログアウトページを作成します。
ログアウト処理の仕様
サーバー
- セッションを削除してログインページへリダイレクト
index.tsへログアウト処理追加
user_idをdeleteして/loginへリダイレクトします。
iniapp.get(
'/logout',
(req: express.Request, res: express.Response): void => {
delete req.session.user_id;
res.redirect('/login');
}
);
アプリケーションを起動
アプリケーションを起動させていきます。
npm scripts へ起動コマンドの追加
実行するコマンドを追記します。
package.json
package.json "scripts": {
"start": "node dist/index.js",
"build": "tsc",
"dev": "ts-node src/index.ts"
},
devでアプリサーバーを起動
yarn devコマンドを実行します。
terminal$ yarn dev
yarn run v1.22.10
$ ts-node src/index.ts
listening on *:8080
8080で待ち受ける形でアプリケーションが起動しました。
アプリの動作テスト
起動させたアプリケーションをブラウザで確認してみます。
入力して送信
ログアウト処理を実行
入力した文字列が表示されているか確認します。
そしてログアウトをクリックしてログインページへ戻るか確認します。
ログイン・ログアウト処理を確認することが出来ました。
Redisのログ確認
起動しているコンテナIDを確認
docker psコマンドで redis のコンテナIDを確認します。
bash$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
11387a81aa9b redis "docker-entrypoint.s…" About a minute ago Up 56 seconds 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp login-sample_redis_1
redisへログイン
docker execコマンドでログインします。
ruby$ docker exec -it 11387a81aa9b bash
root@11387a81aa9b:/data#
キーを確認
保存されているキーを確認します。
ruby127.0.0.1:6379> keys *
1) "sid:sess:nelbdFcxCEp1juSAFvkEmCE18Ol4-aEM"
getで保存されている内容を確認
ログイン時
ログイン時はuser_idが入っていることが確認できました。
swift127.0.0.1:6379> get sid:sess:nelbdFcxCEp1juSAFvkEmCE18Ol4-aEM
"{\"cookie\":{\"originalMaxAge\":1799999,\"expires\":\"2021-06-29T10:07:39.754Z\",\"secure\":false,\"httpOnly\":true,\"path\":\"/\"},\"user_id\":\"xxx\"}"
ログアウト時
ログアウトするとuser_idが削除されていることが確認できました。
swift127.0.0.1:6379> get sid:sess:nelbdFcxCEp1juSAFvkEmCE18Ol4-aEM
"{\"cookie\":{\"originalMaxAge\":1799999,\"expires\":\"2021-06-29T10:25:35.933Z\",\"secure\":false,\"httpOnly\":true,\"path\":\"/\"}}"
以上でログイン・ログアウトの動作確認は完了です。
articleDocker を用いた統一ローカル環境:新人オンボーディングを 1 日 → 1 時間へ
articleDocker で Dev Container を構築:VS Code/Codespaces で即戦力環境を配布
articleDocker マルチステージビルド設計大全:テスト分離・依存最小化・キャッシュ戦略
articleDocker コマンド早見表:build/run/exec/logs/prune を 1 枚で網羅
articleWindows WSL2 に Docker を最適導入:I/O 最適化・メモリ配分・互換性チェック
articleDocker vs Podman vs nerdctl 徹底比較:CLI 互換性・rootless・企業導入の勘所
articlehtmx × Express/Node.js 高速セットアップ:テンプレ・部分テンプレ構成の定石
articleTypeScript で学ぶミドルウェア設計パターン:Express・NestJS の応用例
articleNode.js と Express:API サーバーを高速構築
article【対処法】expressのIPを取得するメソッド req.connectionの非推奨による対応
articleNext.js + Custom Server(Express)でTypeScript保存時にnodemon再起動する設定
articlemkcertでオレオレ認証局とオレオレ証明書を作成しNode.js ExpressサーバーをSSL起動する設定
articleNode.js で ESM の `ERR_MODULE_NOT_FOUND` を解く:解決策総当たりチェックリスト
articleNode.js 本番メモリ運用:ヒープ/外部メモリ/リーク検知の継続監視
articleNode.js で社内 RPA:Playwright でブラウザ自動化&失敗回復の流儀
articleNode.js × Fastify で爆速 REST API:スキーマ駆動とプラグイン設計を学ぶ
articleNode.js クリーンアーキテクチャ実践:アダプタ/ユースケース/エンティティの分離
articlehtmx × Express/Node.js 高速セットアップ:テンプレ・部分テンプレ構成の定石
articleWebRTC が「connecting」のまま進まない:ICE 失敗を 5 分で切り分ける手順
articleWeb Components が “is not a constructor” で落ちる時:定義順序と複数登録の衝突を解決
articleVitest モジュールモック技術の基礎と応用:`vi.mock` / `vi.spyOn` を極める
articleVue.js リアクティビティ内部解剖:Proxy/ref/computed を図で読み解く
articleVite CSS HMR が反映されない時のチェックリスト:PostCSS/Modules/Cache 編
articleTailwind CSS 2025 年ロードマップ総ざらい:新機能・互換性・移行の見取り図
blogiPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
blogGoogleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
blog【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
blogGoogleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
blogPixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
blogフロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
review今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
reviewついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
review愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
review週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
review新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
review科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来



