##はじめに
Passportとはログイン認証に便利なライブラリ。
ただ巷で溢れるサンプルはだいたいExpress3.xで書かれているので、Express4用にメモ。
OAuthだとかOpenIDを使った認証もあるけど、
今回はシンプルにユーザー、パスワードのみで認証してみます。
詳しくはこちら。コードがExpress3だけど。
Passport(公式ページ)
日本語訳ページ
##バージョン
node.js - 0.12.7
express - 4.13.1
passport - 0.3.2
##実装
まずはモデル。認証情報を保持する。
account.js
'use strict';
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var AccountSchema = new Schema({
id: { type: String, required: true },
password: { type: String, required: true },
updated_at: { type: Date },
created_at: { type: Date }
});
AccountSchema.pre('save', function(next) {
var now = new Date();
this.updated_at = now;
if (!this.created_at) {
this.created_at = now;
}
next();
});
module.exports = mongoose.model('Account', AccountSchema);
次にapp.js。
app.js
var express = require('express');
var mongoose = require('mongoose');
var passport = require('passport');
var flash = require('connect-flash');
var session = require('express-session');
var crypto = require('crypto');
var app = express();
app.use(session({ secret: 'hoge' }));
app.use(flash());
app.use(passport.initialize());
app.use(passport.session());
var LocalStrategy = require('passport-local').Strategy;
// 認証
passport.use(new LocalStrategy(
{
usernameField: 'name',
passwordField: 'password',
passReqToCallback: true
},
function (req, name, password, done) {
process.nextTick(function () {
var Account = mongoose.model('Account');
Account.findOne({ "id": name }, function (err, account) {
if (err) return done(err);
if (!account) {
req.flash('error', 'ユーザーが見つかりませんでした。');
req.flash('input_id', name);
req.flash('input_password', password);
return done(null, false);
}
var hashedPassword = getHash(password);
if (account.password != hashedPassword
&& account.password != password) {
req.flash('error', 'パスワードが間違っています。');
req.flash('input_id', name);
req.flash('input_password', password);
return done(null, false);
}
return done(null, account);
});
})
}
));
// 暗号化
var getHash = function(value) {
var sha = crypto.createHmac('sha256', 'secretKey');
sha.update(value);
return sha.digest('hex');
};
// passport
passport.serializeUser(function (account, done) {
done(null, account.id);
});
passport.deserializeUser(function (serializedAccount, done) {
var Account = mongoose.model('Account');
Account.findOne({ "id": serializedAccount }, function (err, account) {
done(err, account.id);
});
});
routingとかsessionの有無チェックとかは省略しております。
ポイントはpassReqToCallbackをtrueにしてリクエストを取得すること。
で、connect-flashのライブラリを読み込んで、入力値やエラーメッセージを設定しています。
usernameField
と passwordField
はhtmlのテキストフィールド'name'値です。
次にログイン処理。
login.js
'use strict';
var express = require('express');
var mongoose = require('mongoose');
var passport = require('passport');
var flash = require('connect-flash');
var router = express.Router();
// ログイン画面表示
router.get('/', function (req, res) {
res.render('login', {
error: req.flash('error'),
input_id: req.flash('input_id'),
input_password: req.flash('input_password')
});
});
// ログイン情報入力
router.post('/', function(req, res, next) {
passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/login',
failureFlash: true
})(req, res, next);
});
module.exports = router;
app.js
でflash
した値をここで取得してrenderしてやる。
login.ejs
<!DOCTYPE html>
<html lang="ja">
<body>
<p><%= error %</p>
<form action="/login" method="POST">
ID:
<input type="text" name="name" value="<%= input_id %>">
Password:
<input type="password" name="password" value="<%= input_password >">
<input type="submit" value="ログイン">
</form>
</body>
</html>