express session と passport.js を用いた認証処理
SPA アプリケーションのサーバーサイドでexpressフレームワークで作成したサーバーの認証処理について、
苦労した点が多かったのでまとめます。仕様は以下の通りです。
- フォーム認証
- passport.js を使用する
- セッション管理は MemoryStore
1.認証処理の実装
認証処理を行うためのクラス Authenticetor.js を作成します。
memorystore モジュールを用いている理由としては、
express session で MemoryStore への保存する場合、 メモリリークを起こす可能性があるためは推奨されていません。
そのため、memorystore モジュールを用いています。
本来は redisDB などを用いた管理にするほうが懸命だと思います。
importpassportfrom'passport';importLocalStrategyfrom'passport-local';importsessionfrom'express-session';importuuidfrom'uuid';constMemoryStore=require('memorystore')(session);// ユーザー取得クラスimportUserfrom'./User';/**
* 認証処理を行うためのクラス
*/exportdefaultclassAuthenticator{/**
* 初期処理
* @param {Object} app
*/staticinitialize(app){this._createSession(app);app.use(passport.initialize());app.use(passport.session());this.serialize();this.deserialize();}/**
* セッション作成
* @param {Object} app
*/static_createSession(app){app.use(session({cookie:{maxAge:6000000},store:newMemoryStore({checkPeriod:6000000}),genid:()=>{returnuuid();},secret:'しーくれっとこーど',rolling:true,resave:false,saveUninitialized:true}));}/**
* セッション格納処理
*/staticsetStrage(){passport.use(newLocalStrategy({usernameField:'id'},async(id,password,done)=>{try{// ユーザー情報取得constuser=User.get(id);if(user&&user.id===id&&user.pass===pass){// ユーザー情報を返却returndone(null,user);}done(null,false);}catch(error){done(null,false);}}));}/**
* serialize処理
*/staticserialize(){passport.serializeUser((user,done)=>{done(null,user);});}/**
* deserialize処理
*/staticdeserialize(){passport.deserializeUser(async(req,id,done)=>{done(null,{id});});}}
2.認証APIにリクエストした際の認証処理
ログインするためのAPIの処理を記述します。
constexpress=require('express');constrouter=express.Router();constpassport=require('passport');router.post('/',passport.authenticate('local'),async(req,res)=>{try{constuserData={id:req.id,hoge:'fuga'}// 何かクライアント側に送りつけたい場合req.session.user=userData;res.send(req.user);}catch(error){res.sendStatus(500);}});
3.app.jsの設定
上記1.で作成したAuthenticatorクラスをapp.jsから呼び出します。
そして、認証のリクエスト以外すべてのリクエストに対して認証チェックを掛け、
上記2.で作成したエンドポイントに認証のルーティングをします。
importAuthenticatorfrom'./modules/Authenticator';::constapp=express();Authenticator.initialize(app);Authenticator.setStrage();:// 認証ルート以外のすべてのルートをチェックapp.use(/^(?!singin)/,function(req,res,next){if(!req.isAuthenticated()){res.sendStatus(401);return;}next();});app.use('/singin',singin);:
まとめ
実装中はめっちゃ苦労しましたが、まとめてみると短いコードでセッション認証をかけることができていると思います。
JWTトークンを用いた場合も似たような形で実装できました。認証もうこわくない!