expressでは、passportの認証機能を利用するのが便利です。
twitterやfacebookなどとも連携できます。
ここではローカルでの認証について、アウトプットとしてまとめました。
expressアプリの作成
```terminal $ npm install -g express-generator $ express --view=pug your-app-name $ cd your-app-name $ npm install ```以降、
$ npm start
でアプリケーションを起動させます。
http://localhost:3000
必要項目のインストール
```terminal $ npm install --save passport $ npm install --save passport-local $ npm install --save express-session ```ログイン実装
```app.js // 既に色々入っているので、そこへ追加 var passport = require('passport'); var LocalStrategy = require('passport-local').Strategy; var session = require('express-session');// signinページの追加
var signinRouter = require('.routes/signin');
app.use('/signin');
// session, passport.initialize, passport.sessionは以下の順番で追加
app.use(session({
secret: "testing",
resave: false,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
// authentication
passport.serializeUser(function(username, done) {
console.log('serializeUser');
done(null, username);
});
passport.deserializeUser(function(username, done) {
console.log('deserializeUser');
done(null, {name:username});
});
passport.use(new LocalStrategy(
{
// signinのformで定義したnameの要素をセット
usernameField: "username",
passwordField: "password"
},
function(username, password, done){
// ここでは、データベースを使わずに、仮にusernameとpasswordを固定で入れています。
if(username == "test" && password == 123456789){
return done(null, username);
}
return done(null, false, {message: "invalid"});
}
));
app.post('/signin',
passport.authenticate('local',
{
failureRedirect: "/signin"
}
),
function(req, res, next){
// res.redirect("/")でreq.userが渡せなかったので、ここでfetchを使っています。
// https://github.com/jaredhanson/passport/issues/244
// fetchは以下のようにインストール
// npm install --save isomorphic-fetch
// var fetch = require('isomorphic-fetch');
fetch("http://localhost:3000/signin",
{
credentials: "include"
}
).then(function(){
res.redirect("/");
}).catch(function(e){
console.log(e);
});
}
);
で、index.pugへリダイレクトした時に、そのページ上にログインしたユーザーの名前を表示します。
```index.js
var express = require('express');
var router = express.Router();
// index.pugをgetした時にコールバックを実行
router.get('/', function(req, res, next) {
console.log(req.user); // {name:'test'}
if (req.user) { // ログインしているユーザーが存在する場合のみ有効
res.render("index", { username: req.user.name});
} else { // ユーザーが存在しなければ、サインインページへ飛ばされる
res.redirect('/signin');
}
});
module.exports = router;
extends layout
block content
h1= username
p Welcome to Express
signin.jsはindex.jsをコピペしてsignin用に書き換えるだけで良いです。
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
res.render("signin", {});
});
module.exports = router;
一応signin.pugも
extends layout
block content
form(action="/signin" method="post")
.username
label username
input(type="text" name="username") // nameはnew LocalStrategyのところで使います。
.password
label password
input(type="password" name="password") // nameはnew LocalStrategyのところで使います。
.signin
input(type="submit")
ログイン時にconsole.log('serializeUser')とconsole.log('deserializeUser')が実行されていることを確認しましょう。
serializeUserだけがコンソールで出力されていてもdeserializeUserが出力されていなければ、ログインは成功していません。
その時は、app.use時のsession、passport.initilizer、passport.sessionを書く順番がおかしくなっていないかとか、誤字脱字等がないかどうかとか、チェックしていってください。
MySQLのユーザー情報を基にログイン
mysqlで適当にデータベースを作ります。mysql> create table users (id int not null primary key, username varchar(20), password int);
とかにして、
mysql> insert into users values (1, 'test', 123456789);
みたいにデータを入れておきます。
次にapp.jsでmysqlを使い、データを取り出してログイン時に入力された値と照合させるようにします。
// npm install --save mysql2
var mysql = require('mysql2');
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'your-password', // mysqlの自分のパスワード
database: 'testdb' // db名は自分で自由に作った名前を当てはめる
});
// 上で書き込んだpassport.useの部分を書き換えます。
passport.use(new LocalStrategy(
{
usernameField: "username",
passwordField: "password"
},
function(username, password, done){
connection.query("select * from users;", function(err, users) {
// usernameもpasswordもユニーク前提
var usernames = [];
var passwords = [];
for (i = 0; i < users.length; i++) {
usernames.push(users[i].username);
// input(type="password")で渡される値はstringのようなので、
// データベースから取り出した値もstringにしています。
var pw = users[i].password.toString();
passwords.push(pw);
}
if (usernames.includes(username) && passwords.includes(password)) {
return done(null, username);
}
return done(null, false, {message: "invalid"});
});
}
));
これで、ログイン時に
ユーザー名: test
パスワード: 123456789
を入れてあげると、ログインできるようになります。
サインアップは、サインアップのフォームを作って、post時に/signupへやってきた時のコールバックにロジックを書いてあげれば良いです。
app.post('/signup', function(req, res, next){
connection.query('select * from users;', function(err, users){
connection.query('insert into users set ? ;', {
username: req.body.username,
email: req.body.email,
password: req.body.password,
created_at: new Date(),
updated_at: new Date()
},
function(err){
console.log("サインアップに関するエラー: " + err);
res.redirect("/signin");
}
);
});
});
まあ、こんな感じで。
サインアウトは、
app.get('/signout', function(req, res, next) {
req.logout();
console.log('ログアウトしました');
res.redirect('/');
});
これだけでOKです。
いい感じのところにサインアウトボタンを配置してあげてください。