2014年1月25日土曜日

ExpressとRedisでセッション管理

今回は、Node.js+Express+EJS+Redisを使ってセッション管理を行ってみます。
これから紹介するサンプルアプリは、「ログインするとマイページに飛び、ログアウトすると再びログイン画面に戻る」だけの簡単なものです。

Redisがすでにインストールされている前提で説明を進めます。

$ mkdir hello-session
$ cd hello-session
まずはいつものようにプロジェクトフォルダを作ります。

connect-redisをインストール

$ sudo npm install -g connect-redis
connect-redisを使うとRedisを使ったセッション管理が簡単になります。

package.json


package.json
$ touch package.json
{
  "name": "hello-session",
  "description": "session test app",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
    "express": "3.x",
    "ejs": "0.x",
    "connect-redis": "1.4.x"
  }
}

$ npm install
package.jsonに従って必要なモジュールをインストールします。

Viewの作成

$ mkdir views
$ touch ./views/header.html
$ touch ./views/login.html
$ touch ./views/content.html
$ touch ./views/footer.html

views/header.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>nodejs session example</title>
</head>
<body>

views/footer.html
</body>
</html>

views/login.html
<% include header.html %>
  
  <div style="color:red">
    <%= typeof(error)!== 'undefined' ? error : '' %>
  </div>
    
  <form method="POST" action="/">
    UserID:
    <input type="text" name="userId">
    <br>Password:
    <input type="password" name="password">
    <br>
    <input type="submit">
  </form>

<% include footer.html %>

views/content.html
<% include header.html %>
  
<div>Welcome! userId:
  <%= userId %>
</div>
<a href="/logout">Logout</a>

<% include footer.html %>

server.js

$ touch server.js
server.js
/* jshint undef: false, unused: false */

// get modules
var express = require('express');
var RedisStore = require('connect-redis')(express);
var app = express();

// configure express
app
  // for ejs
  .engine('.html', require('ejs').__express)
  .set('views', __dirname + '/views')
  .set('view engine', 'html')
  // for using 'POST'
  .use(express.urlencoded())
  .use(express.methodOverride())
  // for connect-redis
  .use(express.query())
  .use(express.cookieParser("mysecret"))
  .use(express.session({
    key: 'app.sess',
    store: new RedisStore(),
    secret: 'secret'
  }));

// the authCheck middleware
app.use(function (req, res, next) {
  console.log("auth middleware called.");
  
  // If already logged in.
  if (req.session.userId) {
    console.log(req.session.userId + " has logged in.");
    return next();
  }
  
  // If not logged in yet and userId NOT exists in params.
  if (!req.body.userId) {
    console.log("Anonymous user.");
    return res.render('login');
  }
  // If not logged in yet and userId exists in params.
  else {
    if (checkAuth(req)) {
      console.log(req.body.userId + " login successful.");
      req.session.userId = req.body.userId;
      console.log("userId:"+req.session.userId);
      return next();
    } else {
      console.log("login failed.");
      return res.render('login', {
        error: "invalid userId/password."
      });
    }
  }
});

/**
 * auth function
 * if userId/password is valid, return true.
 */
checkAuth = function (req) {
  if (req.body.userId == 'akirattii' && 
      req.body.password == 'secret') {
    return true;
  } else {
    return false;
  }
};

app.all('/', function (req, res) {
  console.log("GET or POST /");
  res.render('content', { userId: req.session.userId });
});

app.get('/logout', function (req, res) {
  console.log("/logout");
  req.session.destroy(function(){
    console.log("session destroyed.");
  });
  res.redirect('/');
});

if (!module.parent) {
  app.listen(3000);
  console.log('Express app started on port 3000');
}

authCheckミドルウェアが肝となります。このミドルウェアは、全てのリクエストの直前にログイン状態かどうかを確認しています。未ログインならログイン画面へ飛ばします。


起動と実行

$ nodejs server.js
http://localhost:3000 へアクセスするとログイン画面が表示されます。 userId="akirattii", password="secret" でログインできます。

関連ページ
Nodejs+ExpressでRedisを使うサンプル。
Nodejs+Express+EJSのサンプル

0 件のコメント:

コメントを投稿