ExpressでSessionを扱う方法について取り上げます。「express-session」「cookie-parser」をMiddlewareに指定してSessionを扱えるようにします。今回、Session情報はRedisで管理します。
目次
前準備
Redisを起動
今回、セッション情報はRedisで管理します。
docker-composeでRedis立ち上げます。docker-compose.yml
に以下内容を記述します。
version: '3'
services:
redis:
image: "redis:latest"
ports:
- "6379:6379"
volumes:
- "./data/reis:/data"
dockerを立ち上げます。
$ docker-compose up -d
Redisのデータを確認します。
$ docker-compose ps
Name Command State Ports
-----------------------------------------------------------------------------------------
express_session_redis_1 docker-entrypoint.sh redis ... Up 0.0.0.0:6379->6379/tcp
$ docker exec -it express_session_redis_1 /bin/bash
root@8ab82951a477:/data#
root@8ab82951a477:/data# redis-cli
127.0.0.1:6379>
127.0.0.1:6379> keys *
(empty list or set)
パッケージインストール
必要なパッケージをインストールします。
npm install --save express \
express-session \
cookie-parser \
redis \
connect-redis
cookie-parser
- セッションIDと呼ばれる値がCookieに保存されます。
- クライアントからサーバに再アクセスする際、リクエストヘッダのCookieにセッションIDを指定します。
- リクエストヘッダに指定されたCookieを読み取るために
cookie-parser
が必要となります。 - サーバ側ではCookieから読み取ったセッションIDを利用してセッション情報にアクセスします。
redis
connect-redis
- 今回セッション情報をRedisで管理するため必要となります。
動作確認用コード
app.js
というファイルを作成して以下処理を記述します。
const express = require('express')
const cookieParser = require('cookie-parser')
const session = require('express-session')
const redis = require('redis')
const app = express()
const RedisStore = require('connect-redis')(session)
const redisClient = redis.createClient()
app.use(cookieParser())
app.use(session({
secret: 'secret_key',
resave: false,
saveUninitialized: false,
store: new RedisStore({ client: redisClient }),
cookie: { httpOnly: true, secure: false, maxage: 1000 * 60 * 30 }
}))
app.get('/', (req, res) => {
if (req.session.views) {
req.session.views++
} else {
req.session.views = 1
}
res.json({
'sessionID': req.sessionID,
'req.session.views': req.session.views
})
})
app.listen(5000, () => console.log('Example app listening on port 5000!'))
req.session
でセッション情報にアクセスできます。
同一セッションでアクセスされるたびに req.session.views
がインクリメントされていく処理になっています。
動作確認
Express起動
Expressを起動します。
$ node app.js
Example app listening on port 5000!
curlでアクセス
$ curl -v http://localhost:5000 | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 5000 (#0)
> GET / HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Content-Type: application/json; charset=utf-8
< Content-Length: 70
< ETag: W/"46-epFTMNEhE6iPJMaUVafCPXk7BKk"
< Set-Cookie: connect.sid=s%3AuNPBmH4CKYJhxwuuE8fR5NCg0q2M4LBT.KICNGChskL9c7%2BH5mz6ju33lEUlJwYuds255QTY4wDo; Path=/; HttpOnly
< Date: Fri, 21 Dec 2018 01:58:00 GMT
< Connection: keep-alive
<
{ [69 bytes data]
100 70 100 70 0 0 5000 0 --:--:-- --:--:-- --:--:-- 5000
* Connection #0 to host localhost left intact
* Closing connection 0
{
"sessionID": "uNPBmH4CKYJhxwuuE8fR5NCg0q2M4LBT",
"req.session.views": 1
}
$ curl -v http://localhost:5000 | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 5000 (#0)
> GET / HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Content-Type: application/json; charset=utf-8
< Content-Length: 70
< ETag: W/"46-DCWS9uO2AuRzE+bDZSV1kylvVrc"
< Set-Cookie: connect.sid=s%3AR_mJz2bz_vR1RnqBBqSP4nzzefeS9DE2.u5wCq%2FfUPqtSwShIempPgXLm%2F%2FULISnTTZtu%2F47rXAI; Path=/; HttpOnly
< Date: Fri, 21 Dec 2018 01:59:43 GMT
< Connection: keep-alive
<
{ [69 bytes data]
100 70 100 70 0 0 7000 0 --:--:-- --:--:-- --:--:-- 7000
* Connection #0 to host localhost left intact
* Closing connection 0
{
"sessionID": "R_mJz2bz_vR1RnqBBqSP4nzzefeS9DE2",
"req.session.views": 1
}
上記2回のリクエストでは、Cookieにセッションを指定せずにリクエストしています。
そのため、サーバ側で新たに2つのセッションデータが作られています。
次に、さきほどのリクエストで生成された以下のセッションをCookieに指定してアクセスします。
connect.sid = s%3AR_mJz2bz_vR1RnqBBqSP4nzzefeS9DE2.u5wCq%2FfUPqtSwShIempPgXLm%2F%2FULISnTTZtu%2F47rXAI
$ curl -b connect.sid=s%3AR_mJz2bz_vR1RnqBBqSP4nzzefeS9DE2.u5wCq%2FfUPqtSwShIempPgXLm%2F%2FULISnTTZtu%2F47rXAI -v http://localhost:5000 | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 5000 (#0)
> GET / HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.64.1
> Accept: */*
> Cookie: connect.sid=s%3AR_mJz2bz_vR1RnqBBqSP4nzzefeS9DE2.u5wCq%2FfUPqtSwShIempPgXLm%2F%2FULISnTTZtu%2F47rXAI
>
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Content-Type: application/json; charset=utf-8
< Content-Length: 70
< ETag: W/"46-u9eZecG7jG3vaA3OvXUb5eImPKw"
< Date: Fri, 21 Dec 2018 02:05:01 GMT
< Connection: keep-alive
<
{ [69 bytes data]
100 70 100 70 0 0 1521 0 --:--:-- --:--:-- --:--:-- 1521
* Connection #0 to host localhost left intact
* Closing connection 0
{
"sessionID": "R_mJz2bz_vR1RnqBBqSP4nzzefeS9DE2",
"req.session.views": 2
}
すでに存在するセッションのため req.session.views
の値が2になっています。
保存されたセッションデータを確認
Redisに保存されたセッションデータを確認します。
127.0.0.1:6379> keys *
1) "sess:R_mJz2bz_vR1RnqBBqSP4nzzefeS9DE2"
2) "sess:uNPBmH4CKYJhxwuuE8fR5NCg0q2M4LBT"
127.0.0.1:6379>
127.0.0.1:6379> get sess:R_mJz2bz_vR1RnqBBqSP4nzzefeS9DE2
"{\"cookie\":{\"originalMaxAge\":null,\"expires\":null,\"secure\":false,\"httpOnly\":true,\"path\":\"/\"},\"views\":2}"
127.0.0.1:6379>
127.0.0.1:6379> get sess:uNPBmH4CKYJhxwuuE8fR5NCg0q2M4LBT
"{\"cookie\":{\"originalMaxAge\":null,\"expires\":null,\"secure\":false,\"httpOnly\":true,\"path\":\"/\"},\"views\":1}"
2つセッションデータが存在しており、sess:R_mJz2bz_vR1RnqBBqSP4nzzefeS9DE2
のほうはviews
が2
になっています。