0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

nodejsサーバーでexpress-mysql-sessionをつかう

Last updated at Posted at 2021-12-24

はじめに

ベクトルタイルサーバーを磨き上げる一環で、開発環境で使っていた in-memory session store を mysql のデータベースに置き換えようとしている。

環境

  • Cent OS Linux release 7.8.2003
  • nodejs ver. 16.13.1
  • npm ver. 8.1.2
  • mysql Ver. 8.0.27 for Linux on x86_64 (MySQL Community Server - GPL)

手順

Step1: Azure AD認証つきのnodejsサーバーの準備

nodejs/expressサーバーを作る。msalでのAzure AD認証は Microsoftのチュートリアル (Build Node.js Express apps with Microsoft Graph) を参考につけた。(Azure AD は自分のマイクロソフトアカウントで APPの登録をした。)

ここまでやったレポジトリが ubukawa/server-test-01 で、このことは前の記事 に書いた(まとまっていなくてすみません)。

ここまでの課題と方針

ここまででは、express-session を使っていて、ユーザーの保存がインメモリセッションなのでProduction環境では適切なものに置き換える必要がある。msalClientもlocalsで管理されていて、次にやらないといけないのだが、まずはexpress-session の sessionをやる。mysqlの方がシンプルでよさそうなので express-mysql-session がよいだろうと判断した。

Step2: mysqlのインストール

ベクトルタイルサーバーから、ローカルホストとして立っているユーザー管理データベースにアクセスさせるため、サーバーにmysqlをインストールした。自分のテスト環境はCentOSなので、mysqlのインストールについては以下が非常に参考になり、その手順を守ってインストールした。(ありがとうございます。)

CentOS7にMySQLをインストールして初期設定するまで

そして、専用のユーザーを作り、データベースの作成、レコード追加・削除等の必要そうな権限を与えた。ベクトルタイルサーバーと同じ環境にmysqlを入れてローカルホストへの接続という形でmysqlデータベースにアクセスさせてみることにする。(ただし、これだけでは不十分。step4を参照。)

Step3: express-mysql-session の追加

もともとの app.js をよく見ると、比較的単純に express-session を express-mysql-session に置き換えられるのではないかと思った。まず、express-mysql-sessionのモジュールを追加。

app.jsの冒頭(一部)
const session = require('express-session');
const MySQLStore = require('express-mysql-session')(session); //追加分

Express-session でsessionを使っていたところに、express-mysql-session のセッションストアを指定する。(パスワードとデータベース名は.envに入れて読まるようにしました。)

app.jsの一部
//Session witl mysql (from here)////////////////////////
const mysqlOptions ={
  host: 'localhost',
  port: 3306,
  user: 'hoge',
  password: process.env.MYSQL_PASSWORD, 
  database: process.env.MYSQL_DATABASE
};

const sessionStore = new MySQLStore(mysqlOptions);
const sess = {
  secret: process.env.hoge,
  cookie: {maxAge: 60000000}, 
  store: new MySQLStore(mysqlOptions),
  resave: false,
  saveUninitialized: false
}

sess.cookie.secure = true; //for production
app.use(session(sess))
//Session witl mysql (until here)////////////////////////

/*
//もともとのセッション
app.use(session({
  secret: process.env.hoge,
  resave: false,
  saveUninitialized: false,
  unset: 'destroy'
}));
*/

という感じにして動かしてみた。(ローカルホストではなく、外部の練習サーバーで実験。)
セッションのパラメータについては、最初、cookieのmaxAgeの単位を秒だと勘違いしていたので、えらく早くセッションが切れてしまったのですが、ミリ秒だと気づいてなおしました。resaveとsaveUninitializedは適宜の設定にします。

Step4: エラーの処理

ところが、サーバー側で、
ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client
というエラーがでた。調べてみると、mysqlにアクセスできていないようなので、ベクトルタイルサーバーからmysqlに接続するために、mysqlで以下のコマンドを実行した。

ALTER USER '(決めたユーザー)'@'localhost' IDENTIFIED WITH mysql_native_password BY '(パスワード)';
flush privileges;

そのあと、mysqlのデータベースに値が入るので、sessionストアとして、一応は動いている模様。

Step5: まだ動作しない。

データベースはvtUserとしておいて作っておきました。中身を見るとsessionsというテーブルがあるので、session情報が書き込まれているようです。
2021-12-24-mysql-1.png

一応、セッションの中にはuseIdが入っているものもあるようです。auth.jsのcallbackにきちんと返ってくると、homeidが req.session.userId として記録される。(このリスト、翌日見たら消えていたので、きちんとexpireしたのは消えるのかなと思います。)

2021-12-24-mysql-2.png

ただ、インデックスページが返ってこないので、今確認中です。
sessionの問題というより、コールバックとそのあとのホームページ描画関係のものをいじってしまったのかもしれません。
(作業を継続しているので、出来たら追記します。)


Azure AD認証の時のscope('user.read,calendars.readwrite,mailboxsettings.read'等)の関係の問題のようです。
内部のAzure ADを使ってテストしたらうまくいきました。

まとめ

express-sessionのsessionstoreをmysqlのデータベースにすることができました。

参考にしたページなど

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?