Node.jsのセッション管理をよく理解せずにハマったので振り返り
Node.js + Express でログイン認証機能を実装するというそのものズバリの記事を見つけて、そこの記事中で紹介されている Gistのソースを参考にしたのですが、どうにもうまくいかずに、ハマりました
ハマった要因というか、敗因なんですが、記事をナナメ読みしてて、記事中のMongoというキーワード見て
「ひとまず、Mongoは利用しないのでその部分はパスしてやろう」
と決めたのがどうもまずかったみたいです。。。
そこで、まずは基本となるセッション管理の仕組みについて、順を追って文章にまとめておくことで自分の理解を確認しておこうと思います
まずはサンプルとなるアプリを作成
Node.js+expressで、テンプレートエンジンにJadeを使った構成でアプリを作成します
なお、私の環境ですが
-OS: Mac OS X 10.8.5 - Node.js: 0.10.22
という感じです
mkdir expressSample express expressSample cd expressSample cat package.json { "name": "application-name", "version": "0.0.1", "private": true, "scripts": { "start": "node app.js" }, "dependencies": { "express": "3.4.7", "jade": "*" } } npm install jade@1.1.4 node_modules/jade ├── character-parser@1.2.0 ├── commander@2.1.0 ├── mkdirp@0.3.5 ├── monocle@1.1.51 (readdirp@0.2.5) ├── transformers@2.1.0 (promise@2.0.0, css@1.0.8, uglify-js@2.2.5) ├── with@2.0.0 (uglify-js@2.4.0) └── constantinople@1.0.2 (uglify-js@2.4.9) express@3.4.7 node_modules/express ├── methods@0.1.0 ├── merge-descriptors@0.0.1 ├── range-parser@0.0.4 ├── cookie-signature@1.0.1 ├── fresh@0.2.0 ├── debug@0.7.4 ├── buffer-crc32@0.2.1 ├── cookie@0.1.0 ├── mkdirp@0.3.5 ├── send@0.1.4 (mime@1.2.11) ├── commander@1.3.2 (keypress@0.1.0) └── connect@2.12.0 (uid2@0.0.3, pause@0.0.1, qs@0.6.6, bytes@0.2.1, raw-body@1.1.2, batch@0.5.0, negotiator@0.3.0, multiparty@2.2.0)
アプリの作成が完了したら
node app.js
とします。デフォルトでは、3000ポートを使って起動されるのでこんな感じのメッセージが表示されます
Express server listening on port 3000
ブラウザを起動して、http://localhost:3000/ にアクセスすると以下のメッセージが表示されます
エラーメッセージの
「doctype 5is deprecated, you must now use
doctype html`」
とあり、viewsディレクトリ配下のlayout.jadeのDocTypeを変更しろとのことなので以下のように変更
変更前
doctype 5 html head title= title link(rel='stylesheet', href='/stylesheets/style.css') body block content
変更後
doctype html html head title= title link(rel='stylesheet', href='/stylesheets/style.css') body block content
これで、以下のように意図したようになりました
ログインのフォームの値の受け渡し方法がよくわからなかった
自動的に生成される index.jade を以下のように変更して、ログイン用のフォームを配置してみました
index.jadeのコード
extends layout block content h1= title p Welcome to #{title} form(action='/login') label ログインID: input(type='text',name='username',placeholder='username') br label パスワード: input(type='password',name='password',placeholder='Password') br label.checkbox.gray ログイン状態を保存 input(type='checkbox') br button.btn.btn-primary(type='submit') ログイン
app.jsのコード
上記ログインフォームでSubmitされた時に、GETメソッドで/login ページに飛ぶようにルーティングを設定する必要があるようなので、以下のようにコードを1行追加。
app.get('/', routes.index); app.get('/users', user.list); // 以下1行を追加 app.get('/login', user.login);
/loginにアクセスした場合に、routes/ 以下にある user.jsのloginが呼び出されるという形になるため、routes/user.jsを以下のように修正しました
exports.list = function(req, res){ res.send("respond with a resource"); }; // 以下のコード追加 exports.login = function(req, res){ res.render("login",{title:"login test"}); };
上記loginの中のres.renderのところで、views/配下にある login.jadeが呼び出されて HTML/CSSが生成されるため、login.jadeを以下のようにひとまず作成しました
block content h1= title p This is a login test page #{title}
これでひとまずトップページにあるログインフォームから、ログイン先のページに遷移出来るようになります
ただこれだと肝心のログインID&パスワードの値を引き継いでくれません。
そのため、以下のように修正をしていきます。
app.jsの修正
app.use(express.bodyParser()); app.use(express.cookieParser()); app.use(express.session({ secret: "expressSample" }));
user.jsを修正
exports.login = function(req, res){ var username = req.query.username; var password = req.query.password; console.log("username is " + username); res.render("login",{ title:"login test", username:username, password:password }); };
login.jadeを修正
extends layout block content h1= title p This is a login test page #{title} ul li username: #{username} li password: #{password}
上記3点の修正で、ひとまず、ログインフォームに入力したID&パスワードが画面表示されるまで出来上がりました
まとめ
Webアプリを作り慣れてないこともあり、こういう値の受け渡しについての理解が曖昧だったのですがこうやって1つ1つ順を追って文章にまとめながら、検証したことで以前よりも大分理解が深まった気がします
今回の内容をベースに、次回は ACSと連携させたログイン処理という内容で書いていければと思ってます