node.js+express+mongodb+ajax實現註冊、登陸、驗證碼
完整專案在,歡迎star。
本專案借鑑了,大家也可以去star。
結果展示
實現的功能:
- 主頁面,登陸頁面,註冊頁面
- 註冊密碼兩次輸入
- 驗證碼檢驗
使用的技術
- 使用MongoDB作為後端資料庫儲存使用者資訊
- 使用node.js部署前端
- 採用ajax實現前端與伺服器交換資料
直接輸入網址(http://localhost:8008/)進入主介面,提示需要登陸
進入註冊介面註冊賬號
註冊成功進入主頁面
也可以從登陸介面進入
環境配置
MongoDB
在ubuntu20.04下安裝MongoDB
sudo apt-get install mongodb
在專案目錄下建立MongoDB的資料和日誌目錄
mkdir log mkdir data
啟動MongoDB
mongod --dbpath ./data/ --logpath ./log/mongod.log --fork
檢查MongoDB是否已經啟動
ps aux|grep mongo
輸出為
說明啟動成功。
檢查MongoDB監聽的預設埠
lsof -i:27017
輸出為
和上圖的pid一致,說明埠已經被開啟。
或者在OSX上安裝MongoDB
brew tap mongodb/brew
brew install [email protected]
啟動和關閉
brew services start [email protected] brew services stop [email protected]
配置node.js
sudo apt-get install nodejs
sudo apt-get install npm
在專案下需要安裝的node.js模組
npm install express --save
npm install body-parser --save
npm install cookie-parser --save
npm install multer --save
npm install mongodb --save
其中
-
express是我們使用的前端框架
-
body-parser用於處理 JSON, Raw, Text 和 URL 編碼的資料。
-
cookie-parser解析Cookie
-
multer 用於處理MIME編碼的表單資料。
主要程式碼
後端
專案的後端是Express和MongoDB,在專案目錄下啟動node backend.js
啟動後端。
Express
啟動Express
var express = require('express');
var app = express();
後端程式中需要處理瀏覽器的跨域請求
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
});
設定主頁面、登入和註冊介面
app.get('/main.html', function (req, res) {
res.sendFile(__dirname + '/' + 'main.html');
})
app.get('/login.html', function (req, res) {
res.sendFile(__dirname + '/' + 'login.html');
})
app.get('/register.html', function (req, res) {
res.sendFile(__dirname + '/' + 'register.html');
})
將主介面作為預設介面
app.get('/', function (req, res) {
res.sendFile(__dirname + '/' + 'main.html');
})
為註冊和登入操作新增介面
app.post('/process_login', urlencodedParser, function (req, res) {
var userName = req.body.userName;
var pwd = req.body.pwd;
if (!userName) {
res.json({ code: -1, message: '使用者名稱不能為空' });
} else if (!pwd) {
res.json({ code: -1, message: '密碼不能為空' });
} else {
db.searchUser({ name: userName }, function (result) {
if (result.length > 0) {
if (result[0].name == userName && result[0].pwd == pwd) {
res.json({ code: 0, message: '登入成功' });
} else {
res.json({ code: -1, message: '使用者名稱或密碼錯誤' });
}
} else {
res.json({ code: -1, message: '不存在該使用者' });
}
});
}
})
app.post('/process_register', urlencodedParser, function (req, res) {
var userName = req.body.userName;
var pwd = req.body.pwd;
if (!userName) {
res.json({ code: -1, message: '使用者名稱不能為空' });
} else if (!pwd) {
res.json({ code: -1, message: '密碼不能為空' });
} else {
db.searchUser({ name: userName }, function (result) {
if (result.length > 0 && result[0].name == userName) {
res.json({ code: -1, message: '使用者已存在,可直接登入' });
} else {
// res.json({ code: -1, message: '不存在該使用者' });
db.insertUser({ name: userName, pwd: pwd }, function (insertResult) {
console.log(insertResult)
if (insertResult.insertedCount > 0) {
res.json({ code: 0, message: '註冊成功' });
} else {
res.json({ code: -1, message: '註冊失敗,請重新註冊' });
}
})
}
});
}
})
最後是開啟後端,監聽8008
埠
var server = app.listen(8008, function () {
console.log("後端啟動成功!")
})
MongoDB
建立MongoDB物件
var db = require('./db');
建立db.js
檔案,編寫資料庫相關操作
通過預設埠訪問MongoDB
var mongoClient = require('mongodb').MongoClient;
var url = 'mongodb://127.0.0.1:27017/';
MongoDB會在我們進行資料路操作的時候自動建立相應的資料庫,我們只需要負責編寫插入和查詢的程式碼,資料庫的名字是login_project
,下面是查詢和插入的程式碼
function searchUser(whereStr, callBack) {
mongoClient.connect(url, { useNewUrlParser: true }, function (err, db) {
if (err) throw err;
var dbo = db.db('login_project');
dbo.collection('site').find(whereStr).toArray(function (err, result) {
if (err) throw err;
console.log('查詢指定條件的資料...', result);
callBack(result);
db.close();
})
})
}
function insertUser(myobj, callBack) {
mongoClient.connect(url, { useNewUrlParser: true }, function (err, db) {
if (err) throw err;
var dbo = db.db('login_project');
dbo.collection('site').insertOne(myobj, function (err, res) {
if (err) throw err;
console.log('文件插入成功');
callBack(res);
db.close();
})
})
}
最後,允許這兩個函式被外部檔案呼叫
exports.searchUser = searchUser;
exports.insertUser = insertUser;
前端
前端主要的工作是main.html
、register.html
和login.html
的編寫。
三個介面的公共部分是導航欄
<div id="nav">
<ul>
<li>
<a href="main.html">主頁</a>
</li>
<li>
<a href="login.html">登入</a>
</li>
<li>
<a href="register.html">註冊</a>
</li>
</ul>
</div>
main.html
main.html
頁面通過js
通過url獲得當前的使用者名稱並給出提示
var name = getUrlParameter('name');
console.log(name);
if(name != ""){
document.getElementById("info").innerHTML = "當前登陸的賬號為:" + name;
}
function getUrlParameter(name){
name = name.replace(/[]/,"\[").replace(/[]/,"\[").replace(/[]/,"\\\]");
var regexS = "[\\?&]"+name+"=([^&#]*)";
var regex = new RegExp( regexS );
var results = regex.exec(window.parent.location.href );
if( results == null ) return "";
else {
return results[1];
}
};
通過上面的js
自動更改html中的資訊
<div class="wrapper">
<h1 id="info"></h1>歡迎使用NJU-SE-Web系統</h1>
<h1 id="info">請登陸!</h1>
</div>
login.html
登陸介面如下
<div class="wrapper">
<h1>歡迎登入NJU-SE-Web系統</h1>
<div class="form-list">
<div class="form-item">
<span>使用者名稱:</span>
<input type="text" name="username" id="name" />
</div>
<div class="form-item">
<span>密碼:</span>
<input type="password" name="userpwd" id="pwd" />
</div>
<div class="form-item">
<canvas id="verifi-code" style='width:110px;height:25px'></canvas>
<input id="input-code" type="text" placeholder="請輸入驗證碼">
</div>
<div class="btn">
<button onclick="submit()">登入</button>
</div>
</div>
</div>
使用js完成登陸後的頁面切換和資料庫查詢
function submit() {
var name = $("#name").val().trim();
var pwd = $("#pwd").val().trim();
$.ajax({
url: "http://127.0.0.1:8008/process_login",
type: "post",
data: {
userName: name,
pwd: pwd
},
success: function(res) {
console.log(res);
if (res.code == 0) {
window.location.href = 'main.html?name=' + name;
} else {
alert(res.message);
}
},
error: function(){
console.info("網路出錯");
alert("網路出錯,請再試一次");
}
})
}
其中,通過url將登陸使用者的資訊傳遞給main.html
頁面。
如果ajax請求成功則頁面跳轉,如果登陸失敗則給出提示資訊。
通過js程式碼實現驗證碼生成
function createCode() {
let code = "";
var codeLength = 4;
var selectChar = new Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9,'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z');
for (var i = 0; i < codeLength; i++) {
var charIndex = Math.floor(Math.random() * 36);
code += selectChar[charIndex];
}
return code;
}
在canvas上畫出驗證碼
function draw_canvas(code) {
if (canvas) {
var ctx=canvas.getContext('2d');
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.font="80px Verdana";
ctx.strokeText(code,25,110);
console.log("canvas 繪製完成")
}
else
console.log("沒有找到canvas")
}
編寫函式檢查字串是否相同,並給出提示
function isequal(str,str1,alert_info){
if(str != str1){
alert(alert_info);
return false;}
else return true;
}
在submit
函式中檢查
var input_code = $("#input-code").val().trim();
if(!isequal(code, input_code, "驗證碼錯誤")) return;
同時,需要在載入頁面時載入這個驗證碼
var canvas = document.getElementById('verifi-code');
var code = '';
window.onload = function () {
code = createCode();
draw_canvas(code);
}
以及支援驗證碼點選重新整理
canvas.onclick = function () {
code = createCode();
draw_canvas(code);
}
register.html
register.html
和login.html
大致相同,主要的區別是register.html
需要對密碼進行二次驗證,在submit
函式中進行檢驗
var pwd = $("#pwd").val().trim();
var pwda = $("#pwda").val().trim();
if(!isequal(pwd, pwda, "兩次輸入不一致")) return;
如果驗證通過,則向資料庫中插入資訊,如果ajax請求成功,則實現跳轉
success: function(res) {
console.log(res);
if (res.code == 0) {
alert("註冊成功");
window.location.href = 'main.html?name=' + name;
} else {
alert(res.message);
}
},