iT邦幫忙

2

[NodeJS] 第一次 NodeJS 就上手 Part 4

  • 分享至 

  • xImage
  •  

前面的 Part 3 講了預設的 Session,現在來提一下 MongoDB 與 Redis 的儲存方式,篇幅夠的話,順便會提到 Cookie base 的儲存方法。
Session in MongoDB

在 Express 當中,Session 預設儲存的方式是記憶體。如果你要儲存在資料庫中也是可以的,關於資料庫呢,這邊除了 MongoDB 之外,還有另外一個,叫做 Redis。他與 MongoDB 一樣是 key/value 的資料庫。差別大概在他有 VMware sponsored 這樣吧(喂

由於先前我們已經介紹過 MongoDB,所以這邊先以 MongoDB 的儲存方式來介紹。雖然 Connect 推薦使用 Redis 來作儲存媒介,不過也沒硬性規定就是。

BUT!

原生的寫法是行不通的,

(function() {
  var app, express, mongo, mongoServer;

  express = require('express');

  mongo = require('mongodb');

  mongoServer = new mongo.Server('localhost', 27017, {
    auto_reconnect: true,
    pooSize: 5
  });
/home/hinablue/workspace/works/jsdc/
  app = express.createServer();

  app.configure(function() {
    this.use(express.cookieParser());
    return this.use(express.session({
      secret: "@#$TYHBVGHJIY^TWEYKJHNBGFDWGHJKUYTWE#$%^&*&^%$#",
      store: new mongo.Db('mysession', mongoServer)
    }));
  });

  app.get("/", function(req, res) {
    console.info(req.session.item);
    req.session.item = 'Hello World';
    return res.send('Hello World');
  });

  app.listen(3000, function() {
    return console.info("Express server listening on port " + (this.address().port) + " in " + process.env.NODE_ENV + " mode");
  });

}).call(this);

馬上就會出現錯誤,

$ node test.js
Express server listening on port 3000 in development mode
TypeError: Object #<Db> has no method 'get'
    at Object.session [as handle] (/home/hinablue/node-in-session/node_modules/express/node_modules/connect/lib/middleware/session.js:318:11)
    at next (/home/hinablue/node-in-session/node_modules/express/node_modules/connect/lib/http.js:203:15)
    at Object.cookieParser [as handle] (/home/hinablue/node-in-session/node_modules/express/node_modules/connect/lib/middleware/cookieParser.js:44:5)
    at next (/home/hinablue/node-in-session/node_modules/express/node_modules/connect/lib/http.js:203:15)
    at Object.handle (/home/hinablue/node-in-session/node_modules/express/lib/http.js:83:5)
    at next (/home/hinablue/node-in-session/node_modules/express/node_modules/connect/lib/http.js:203:15)
    at HTTPServer.handle (/home/hinablue/node-in-session/node_modules/express/node_modules/connect/lib/http.js:216:3)
    at HTTPServer.emit (events.js:70:17)
    at HTTPParser.onIncoming (http.js:1514:12)
    at HTTPParser.onHeadersComplete (http.js:102:31)

不要問我為什麼,這個問題是 mongodb-native 中的動作,跟 Connect 中的作法不同所導致。所以,請使用 connect-mongo

(function() {
  var app, express, mongoStore;

  express = require('express');

  mongoStore = require('connect-mongo')(express);

  app = express.createServer();

  app.configure(function() {
    this.use(express.cookieParser());
    return this.use(express.session({
      secret: "@#$TYHBVGHJIY^TWEYKJHNBGFDWGHJKUYTWE#$%^&*&^%$#",
      store: new mongoStore({
        host: 'localhost',
        port: 27017,
        db: 'mysessions',
        collection: 'sessions'
      })
    }));
  });

  app.get("/", function(req, res) {
    console.info(req.session.item);
    req.session.item = 'Hello World';
    return res.send('Hello World');
  });

  app.listen(3000, function() {
    return console.info("Express server listening on port " + (this.address().port) + " in " + process.env.NODE_ENV + " mode");
  });

}).call(this);

然後我們從 console 進去 mongo 查看一下,

$ mongo
MongoDB shell version: 2.0.4
connecting to: test
> show dbs
local (empty)
mysessions    0.203125GB
> use mysessions
switched to db mysessions
> show collections
sessions
system.indexes
> db.sessions.find()
{ "_id" : "vB4Gd1rZJQ8e6s0rbE0rEqrR.c0VnxIUGAxsQfi9zA2XoQ9lV9oIs5ULsn+Y/99wu1pI", "session" : "{\"lastAccess\":1334752463452,\"cookie\":{\"originalMaxAge\":14400000,\"expires\":\"2012-04-18T16:34:23.452Z\",\"httpOnly\":true,\"path\":\"/\"},\"item\":\"Hello World\"}", "expires" : ISODate("2012-04-18T16:34:23.452Z") }
>

這樣你就看到我們剛剛存的東西了。

Session in Redis

另外就是 Redis 了,首先要安裝,

$ sudo apt-get install redis-server

然後我們改寫一下,

(function() {
  var app, express, redisStore;

  express = require('express');

  redisStore = require('connect-redis')(express);

  app = express.createServer();

  app.configure(function() {
    this.use(express.cookieParser());
    return this.use(express.session({
      secret: "@#$TYHBVGHJIY^TWEYKJHNBGFDWGHJKUYTWE#$%^&*&^%$#",
      store: new redisStore()
    }));
  });

  app.get("/", function(req, res) {
    console.info(req.session.item);
    req.session.item = 'Hello World';
    return res.send('Hello World');
  });

  app.listen(3000, function() {
    return console.info("Express server listening on port " + (this.address().port) + " in " + process.env.NODE_ENV + " mode");
  });

}).call(this);

然後用瀏覽器跑一下,我們再用 redis-cli 來看看儲存的結果,

$ node test.js
Express server listening on port 3000 in development mode
undefined
Hello World

$ redis-cli
redis 127.0.0.1:6379> KEYS *
1) "sess:8nQiHfxTHfouhSaB5tgj1cQY.UP0VLd1qOneh0D30H2+ivDyYLlX/GcXLdIl9dczWAlg"
redis 127.0.0.1:6379> MGET "sess:8nQiHfxTHfouhSaB5tgj1cQY.UP0VLd1qOneh0D30H2+ivDyYLlX/GcXLdIl9dczWAlg"
1) "{\"lastAccess\":1334753540196,\"cookie\":{\"originalMaxAge\":14400000,\"expires\":\"2012-04-18T16:52:20.197Z\",\"httpOnly\":true,\"path\":\"/\"},\"item\":\"Hello World\"}"
redis 127.0.0.1:6379> exit

這樣就會發現,我們剛剛所儲存的 Session 了!

Session in Cookie

最後我們來說一下 Cookie base 的儲存方式。這個儲存方式有 Cookie 先天的限制,所以,如果你的 Session 所儲存的內容過多(大於 4kb),或是你有些敏感的資料的話,是不建議使用這種方式來儲存的。

(function() {
  var app, connect, express;

  connect = require('connect');

  express = require('express');

  app = express.createServer();

  app.configure(function() {
    this.use(express.cookieParser('@#$TYHBVGHJIY^TWEYKJHNBGFDWGHJKUYTWE#$%^&*&^%$#'));
    return this.use(express.cookieSession());
  });

  app.get("/", function(req, res) {
    console.info(req.session.item);
    req.session.item = 'Hello World';
    return res.send('Hello World');
  });

  app.get("/page2", function(req, res) {
    console.log(req.session.item);
    return res.send(req.session.item);
  });

  app.listen(5000, function() {
    return console.info("Express server listening on port " + (this.address().port) + " in  mode");
  });

}).call(this);

執行結果呢?

$ node test.js
Express server listening on port 3000 in development mode
Hello World
Hello World

你會發現,我一打開瀏覽器就會出現 Session 的資料了,為什麼?因為這是用 Cookie 儲存的關係,所以不要問我為什麼。另外,注意! express.cookieParser() 裡面的 secret 一定要寫,不然會錯誤喔!

我這裡貼上 Header 的結果給大家參考一下,

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Charset:UTF-8,*;q=0.5
Accept-Encoding:gzip,deflate,sdch
Accept-Language:zh-TW,zh;q=0.8,en-US;q=0.6,en;q=0.4
Cache-Control:max-age=0
Connection:keep-alive
Cookie:connect.sid=dj5sq4si22fODOemcEpTrGzT.h%2BHj4JNtvtQpJp%2BA6pUdh1xiEzTv0hoZH%2BLy%2FKr9%2F1g; connect.sess=j%3A%7B%22item%22%3A%22Hello%20World%2C%20asdjfkla%3Bdfja%3Blskdfja%3Bsldkfja%3Bsldfjas%3Bldfja%3Bsldfkjas%3Bldfja%3Bsldfjka%3Bdlfja%3Bsldfjka%3Bsldfja%3Bldkjfa%3Bsldfj%22%7D.41ZpYhK3SpKO5CxWXwa1eJlODvp%2Fj1%2BE9a0dbFL9emk
Host:localhost:5000
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.24 Safari/536.5

請注意 Cookie 的部份,這個部份有 connect.sess 這是 Connect 預設的,裡面是加密過的資料,當你所儲存的 Session 越多時,這個東西就會越來越長。如果過長會炸掉,就這樣!

結語

Session 還是用 DB 來存會好一點,就這樣啦(飄走


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言