LoginSignup
4
2

More than 1 year has passed since last update.

Next.js、next-iron-sessionでのセッション管理(ログインユーザー管理の例)

Last updated at Posted at 2021-10-25

まずインストール

  1. npm add next-iron-session
    →必須。サーバーサイドのセッション管理用
  2. npm install serverless-mysql
    →MySQL実行用。ユーザ認証方法によってはいらない。
  3. 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でサーバーサイドのセッション管理を行いたい方は参考にしてください。

以上です。

4
2
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
4
2