使用Node.js + Express + MySQL + Passport创建简单的登录功能
首先
登录功能虽然非常基本,但从某种意义上来说也是非常重要的功能。
最近,我们不再将密码保存在自己的数据库中,而是可以使用Google或Facebook的ID来代替。因此,在个人运营的网站等方面,个人信息管理的重要性似乎有所降低。
在这里,我们将使用nodejs + express + mysql来编写登录功能和方法。
环境
Windows 10
MySQL 8.0.31
Express: 4.18.2
代码
MySQL是一种开源的关系型数据库管理系统。

NodeJs
npm install passport passport-local express-session
const express = require('express');
const mysql = require('mysql');
const app = express();
const bodyParser = require('body-parser');
require('dotenv').config()
app.use(bodyParser.urlencoded({ extended: true }));
app.set('view engine', 'ejs')
app.use('/public', express.static('public'))
// mysqlに接続
const con = mysql.createConnection({
host: 'localhost',
user: 'root',
password: process.env.MYSQL_PASSWORD,
database: 'nodejs',
dateStrings: "date",
multipleStatements: true
});
// 他のファイルでmysqlを使えるようにexportします
module.exports = con
con.connect((err) => {
if (err) {
console.log('error connecting: ' + err.stack);
return;
}
});
// ここでlogin関連のapiを管理
app.use('/', require('./routes/login.js'));
app.listen(8080, function () {
console.log('listening on 8080')
});
var router = require('express').Router();
// mysql
const con = require('./../server.js')
// loginを管理できるライブラリー
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const session = require('express-session');
router.use(session({ secret: '1234', resave: true, saveUninitialized: false }));
router.use(passport.initialize());
router.use(passport.session());
// loginページ
router.get('/login', function (req, res) {
res.render('login.ejs')
});
// login
// loginに失敗した場合、/failに飛ばす
router.post('/login', passport.authenticate('local', { failureRedirect: '/fail' }), function (req, res) {
res.redirect('/')
});
passport.use(new LocalStrategy({
// id, pw のそれぞれのinputのnameと合わせる
usernameField: 'id',
passwordField: 'pw',
session: true,
passReqToCallback: false,
}, function (input_id, input_pw, done) {
const sql = `select * from accounts where id = '${input_id}'`
con.query(sql, function (err, result) {
// mysql から取り出したaccounts情報から1番目の情報と照合する
// 実際はもっとちゃんとした方がいいですが、なるべくシンプルに
login_data = result[0]
if (err) return done(err)
if (!login_data) return done(null, false, { message: 'account does not exist' })
if (input_pw == login_data.pw) {
return done(null, login_data)
} else {
return done(null, false, { message: 'wrong password' })
}
})
}));
// ログインに成功したらuser.idのセッションを生成し、Cookieを作る
passport.serializeUser(function (user, done) {
done(null, user.id)
});
passport.deserializeUser(function (user_id_saved, done) {
// ユーザーの情報をDBから探す
const sql = `select * from accounts where id = '${user_id_saved}'`
con.query(sql, function (err, result) {
done(null, result[0])
})
});
// ミドルウェアでログイン有無によるページ接近の管理
function is_login(req, res, next) {
if (req.user) {
// loginした状態なら、通す
next()
} else {
// loginしてないならこのページに飛ばす
res.render('login.ejs')
}
}
// ミドルウェアでログインしているかチェックし、ログインしているならreq.userのDBを見せる
router.get('/mypage', is_login, function (req, res) {
// deserializeUserで得られたuserのDBデータ持ってくる
console.log(req.user)
res.send(req.user)
})
module.exports = router;
ejs(html) 可以用以下方式进行近义词表达:嵌入动态HTML模板的EJS。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css"
integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N"
crossorigin="anonymous"
/>
<title>Document</title>
</head>
<body>
<div class="container mt-4">
<form action="/login" method="POST">
<div class="form-group">
<label>id</label>
<input type="text" class="form-control" name="id" />
</div>
<div class="form-group">
<label>pw</label>
<input type="text" class="form-control" name="pw" />
</div>
<button type="submit" class="btn btn-danger">login</button>
</form>
</div>
</body>
</html>
只配备了最基本的输入框和按钮。
登录
登录失败

成功登录

曲奇饼 (qǔ qí

登录后,可以看到生成了Cookie。这证明了登录状态,并且服务器可以从Cookie中获取当前用户信息的一部分。

登录后,从数据库中提取用户信息。通过这样可以在我的页面上显示个人信息,并且可以进行个人信息和密码的更改。
最后
这段代码虽然看起来很长且复杂,但实际上只是从数据库中提取与所输入的ID匹配的数据,并且如果密码也匹配,则登录成功;否则登录失败。然后将该ID的信息保存在Cookie中,在需要的时候从数据库中提取并使用。
其他功能都由库来完成。
虽然此次的介绍是基于mysql的,但是原理在其他数据库,如mongoDB等,也是相同的,因此可以使用passport库来实现登录功能。