Contents
前提
環境はこの人です。
Express, express-session, Sequelize が入っている前提で進めます。
https://github.com/mayarin/NodejsMySQLDocker
作業内容
以下のテーブルを作りました。
CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL, `mailaddress` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL, `password` text COLLATE utf8mb4_bin, `active` tinyint(1) DEFAULT NULL, `createdAt` datetime NOT NULL, `updatedAt` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
アカウント登録時には
・既存メルアド確認
・アカウント作成後自動ログイン
とします。
既存メルアド確認には、SequelizeのfindAndCountAllを利用します。
const { count, rows } = await db.Users.findAndCountAll({
where: {
mailaddress: req.body.mailaddress
},
offset: 0,
limit: 1
});
if(count == 0){
// 行がない場合のみアカウント登録処理
} else {
// アカウントが重複している旨エラーを返す
}アカウント登録の実作業は、Sequelizeのcreateを利用します。
let hashed_password = bcrypt.hashSync(req.body.password, 10);
// パスワードを平文で持たず暗号化します
const newUser = await db.Users.create({
name: req.body.name,
mailaddress: req.body.mailaddress,
password : hashed_password,
active: true
});
if (newUser){
req.session.user = {id: newUser.id};
signup_failed_reason = '';
} else {
signup_failed_reason = 'アカウント登録に失敗しました。';
}パスワードの暗号化にはbcryptを利用しました。
https://www.npmjs.com/package/bcrypt
https://qiita.com/tatsumi44/items/83ac5c18f213e22ed322
パスワード照合でハマりました
一方ログイン時にパスワードを照合するところでハマりました。
router.post('/login', async function(req, res) {
login_mailaddress = req.body.mailaddress;
let hashed_password = bcrypt.hashSync(req.body.password, 10);
const { count, rows } = await db.Users.findAndCountAll({
where: {
mailaddress: req.body.mailaddress,
password: hashed_password,
},
offset: 0,
limit: 1
});いつもはCI4では以下の様に書いていて(多分めちゃくちゃ自己流)。
$password_query = sprintf("select HEX(AES_ENCRYPT('%s', '%s')) as enc_password", $this->request->getVar('update_password'), LOGIN_ENCRYPT_KEY);
$enc_password = $this->db->query($password_query)->getRowArray()['enc_password'];
// こいつを作ってアカウント検索時のwhere句に入れるこれと同じノリで照合しようと思ったんですが、生成するたびに違う暗号文が吐き出されるんです。
これbcryptでは考え方がそもそも誤っていて、compareSyncで照合するんです。
そうなると、メルアドの有無確認→パスワードの照合という流れになります。
完成品はこうなりました。
router.post('/login', async function(req, res) {
login_mailaddress = req.body.mailaddress;
const { count, rows } = await db.Users.findAndCountAll({
raw: true,
where: {
mailaddress: req.body.mailaddress,
},
offset: 0,
limit: 1
});
if(count == 0){
login_failed_reason = 'アカウントがありません。';
res.redirect('/');
} else {
var row = rows[0];
if (bcrypt.compareSync(req.body.password, row.password) ) {
req.session.user = {id: row.id};
} else {
login_failed_reason = 'パスワードが誤っています。';
}
res.redirect('/');
}
});参考サイト
https://qiita.com/tatsumi44/items/83ac5c18f213e22ed322
なおこの段階のgithubはこちらになります。
https://github.com/mayarin/NodejsMySQLDocker/releases/tag/20201102