はじめに
「Node.jsってどんなもんなんだろう?」ってところから始まり。
↓
「へぇ〜APIとか簡単にできるじゃん」となり。
↓
「ログイン認証とかも割と簡単なんじゃね」と思ったのでやってみました。
環境
- macOS Mojave
Express
npm
を使ってExpressをインストールする。
entry pointはapp.js
に設定する。
$ mkdir myapp
$ cd myapp
$ npm init
$ npm install express
myappにapp.js
を作成し、以下を実装する。
const express = require('express')
const app = express()
app.get('/', (req, res) => {
res.send('Hello World')
})
app.listen(3000, () => {
console.log('Listening on prot 3000')
})
普通にnode app.js
で起動しても良いが、変更に対して自動的に起動するようにしてほしいのでnodemon
をインストールする。
起動したら、http://localhost:3000
にアクセスし期待通りの動きをしているか確認する。
$ npm install nodemon -g
$ npx nodemon app.js
[nodemon] starting `node app.js`
Listening on prot 3000
Passport
ログイン認証に必要なものをインストールします。
(詳しく説明しませんが、ググれば大丈夫)
$ npm install body-parser
$ npm install cookie-parser
$ npm install express-session
$ npm install passport
$ npm install passport-local
$ npm install connect-ensure-login
public
フォルダを作成し、login.html
、ok.html
、ng.html
を作成する
const express = require('express')
const app = express()
const path = require('path')
const session = require('express-session')
const passport = require('passport')
const bodyParser = require('body-parser')
const cookieParser = require('cookie-parser')
const LocalStrategy = require('passport-local').Strategy;
app.use(express.static(path.join(__dirname, 'public')))
app.use(cookieParser())
app.use(bodyParser.urlencoded({ extended: true }))
app.use(session({
secret: 'secret',
resave: false,
saveUninitialized: false,
}))
app.use(passport.initialize())
app.use(passport.session())
passport.use(new LocalStrategy((username, password, done) => {
if (username !== 'user' || password !== 'passwd') {
return // ログイン失敗
}
return done(null, username) // ログイン成功
}))
passport.serializeUser((user, done) => {
done(null, user)
})
passport.deserializeUser((user, done) => {
done(null, user)
})
// ...
<html>
<head lang="ja">
<meta charset="UTF-8">
<title>ログイン</title>
</head>
<body>
<form action="/login" method="post">
<div>
<label>ユーザID:</label>
<input type="text" name="username">
</div>
<div>
<label>パスワード:</label>
<input type="password" name="password">
</div>
<div>
<input type="submit" value="Login">
</div>
</form>
</body>
</html>
その他
ログインに成功したら/login/ok
へリダイレクト、失敗したら/login/ng
へリダイレクトするような実装をします。
ただ、普通にやってしまうとログインに成功していないにも関わらず、http://localhost:3000/login/ok
と叩けばアクセスできてしまいます。。。
そこで便利なものがあります!
require('connect-ensure-login').ensureLoggedIn('/login')
を挟んでやれば、ログインしていない場合は指定した/login
にリダイレクトされるようにできます。
// ...
app.get('/', (req, res) => {
res.redirect('/login')
})
app.get('/login', (req, res) => {
res.sendFile('login.html', { root: path.join(__dirname, 'public') })
})
app.post('/login',
passport.authenticate('local', { failureRedirect: '/login/ng', session: true }),
(req, res) => {
res.redirect('/login/ok')
}
)
app.get('/login/ng', (req, res) => {
res.sendFile('ng.html', { root: path.join(__dirname, 'public') })
})
app.get('/login/ok',
require('connect-ensure-login').ensureLoggedIn('/login'), // <--- こいつ!!
(req, res) => {
res.sendFile('ok.html', { root: path.join(__dirname, 'public') })
});
app.get('/logout', (req, res) => {
req.logout()
res.redirect('/login')
})
// ...
最後に
ログイン認証のセッション管理などをreq.isAuthenticated()
で制御させてみたんですけど、想定通りの動きはしなかった。。。
これからはconnect-ensure-login
を使っていこーっと
一応、ソースコードを載せておきます。