まずインストール
- npm add next-iron-session
→必須。サーバーサイドのセッション管理用 - npm install serverless-mysql
→MySQL実行用。ユーザ認証方法によってはいらない。 - npm i sql-template-strings
→MySQLのセキュリティ用(インジェクション防止)
まず、/libフォルダと、その中にsession.tsを作成。
(next-iron-sessionの公式のgitHubから流用)
/lib/session.ts
import { NextApiRequest, NextApiResponse } from "next";
import { Session, withIronSession } from "next-iron-session";
// optionally add stronger typing for next-specific implementation
export type NextIronRequest = NextApiRequest & { session: Session };
export type NextIronHandler = (
req: NextIronRequest,
res: NextApiResponse,
) => void | Promise<void>;
const withSession = (handler: NextIronHandler) =>
withIronSession(handler, {
password: process.env.SECRET_COOKIE_PASSWORD ?? '',
cookieName: "next-iron-session/examples/next.js",
cookieOptions: {
// the next line allows to use the session in non-https environments like
// Next.js dev mode (http://localhost:3000)
secure: process.env.NODE_ENV === "production",
},
});
export default withSession;
ポイント
1. 全体の構造として、
import { Session, withIronSession } from "next-iron-session";
でインポートした、withIronSessionに、
・handler(実際にapiとして処理を行いたい関数)
・sessionに関連するオプション
を渡しています。
handlerとなる関数は、通常のNext.jsのNode.jsのエンドポイント同様に、(req, res)の引数を受け取りますが、
(リクエスト, レスポンスの省略です。)
ここでのreqは NextIronRequestという型で、
本来のNextApiRequest型+Sessionも保持しています。
このSessionの中を覗いてみると、
export type Session = {
set: <T = any>(name: string, value: T) => T;
get: <T = any>(name: string) => T | undefined;
unset: (name: string) => void;
destroy: () => void;
save: () => Promise<string>;
};
このようにセッターやゲッター等、セッションの操作に使う関数が含まれていることがわかります。
これらを受けとったwithIronSessionを返す関数として、withSessionが作られ、エクスポートされることで実際に呼び出すapiで使用されます。(後述)
2. withIronSessionの第2引数として、セッションに関するオプションが用意されます。
他にも詳細な設定が可能ですので、next-iron-sessionの公式のドキュメントも参照してみてください。
password:env内で定義します。32文字以上のパスワードにする必要があるそうです。
cookieName:セッション情報と対になるクッキーの名称です。一応デバッグツール等を使うとユーザから見えるものになりますので、少し気を遣いましょう。
cookieOptions:保持時間など設定できますので、公式ドキュメントを見て必要なオプションを設定しましょう。
これらを呼び出し使用する、api側のファイルは以下のような感じです。
/api/login.ts
import withSession from '../../lib/session' //↑のファイルをインポート
const db = require('../../lib/mysql')
const escape = require('sql-template-strings')
type PostData = {
email: string;
password: string;
}
type UserData = {
...
}
export type QueryResult = {
loginResult: UserData;
}
{
export default withSession(async (req, res) => {
const postData: PostData = req.body;
const queryResult = await db.query(escape`
SELECT
...
FROM
USERS_LIST
WHERE
EMAIL = ${postData.email}
AND PASSWORD = ${postData.password}
`);
let loginResult;
if (queryResult) {
req.session.set("SESSION_USER", queryResult[0]);
await req.session.save();
loginResult = queryResult[0];
} else {
loginResult = {};
}
res.status(200).json({ loginResult });
});
今回はMySQLのユーザーテーブルを使ってのログイン認証+ユーザーログイン情報のセッション保持になっていますが、
そのほかの認証でも、next-iron-sessionのセッション保持機能を使えます。
ポイント
1.インポートしたwithSession関数の引数(handler)として、実行した関数を渡します。
この中で、
req.session.set("SESSION_USER", queryResult[0]);
await req.session.save();
とすることで、reqに含まれるsessionのセッターなどの関数が実行できます。
ここでは、req.session.set(キー, 値)を使ってセッションに値を保持しています。
この後、ユーザー情報をセッションから取得したい場合、
const user = req.session.get("SESSION_USER") ? req.session.get("SESSION_USER") : {};
等として、ユーザー情報を取得できます。
req.session.destroy();
とすると、セッションを破棄し、ログアウト時の処理も実装できます。
いずれも
export default withSession(async (req, res) => {})
の中で実行します。
必要に応じてapiを作成してください。
公式のgitHubなどを見れば、なんとなく使える人が多いとは思いますが、
日本語の記事は少ないので、Next.jsでサーバーサイドのセッション管理を行いたい方は参考にしてください。
以上です。