使用express实现登录注册
使用express实现一个简易的登录注册,(使用session保存登录状态)
登录注册
项目代码结构
项目使用到的插件package.json
{
"name": "4express-login",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"art-template": "^4.13.2",
"blueimp-md5": "^2.16.0",
"body-parser": "^1.19.0",
"bootstrap": "^3.4.1",
"express": "^4.17.1",
"express-art-template": "^1.0.1",
"express-session": "^1.17.1",
"jquery": "^3.5.1",
"mysql": "^2.18.1"
}
}
项目准备
生成package.json文件 【npm init】
安装express,使用命令【npm install express】
安装 art-template
npm install --save art-template
npm install --save express-art-template
安装body-parser npm i body-parser -s
该项目使用的是 bootStrap 所以需要安装bootstrap
npm install bootstrap@3
数据存储在mysql中,安装mysql
npm i mysql
// express本身没有session功能
//使用第三方中间件 express-session
npm i express-session
安装blueimp-md5,给密码加密
npm i blueimp-md5
页面显示
注册页面页面
界面展示
代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap 101 Template</title>
<!-- Bootstrap -->
<link href="../node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- HTML5 shim 和 Respond.js 是为了让 IE8 支持 HTML5 元素和媒体查询(media queries)功能 -->
<!-- 警告:通过 file:// 协议(就是直接将 html 页面拖拽到浏览器中)访问页面时 Respond.js 不起作用 -->
<!--[if lt IE 9]>
<script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
<![endif]-->
<style>
.register-container {
width: 80%;
border: 1px solid #e9e9e9;
margin: 150px auto;
padding: 20px 10%;
border-radius: 5px;
box-shadow: 5px 5px 5px 0 #e9e9e9;
}
.register-btn-container button{
width: 100%;
background: rgb(0, 220, 0);
}
</style>
</head>
<body>
<div class="row">
<div class="col-md-4"></div>
<div class="col-md-4">
<div class="register-container">
<form id="register-form">
<div class="form-group">
<label for="nameInput">姓名</label>
<input type="text" name="user_name" class="form-control" id="nameInput" placeholder="姓名">
</div>
<div class="form-group">
<label for="account">帐号</label>
<input type="text" name="user_account" class="form-control" id="account" placeholder="帐号">
</div>
<div class="form-group">
<label for="password">密码</label>
<input type="password" name="user_password" class="form-control" id="password" placeholder="密码">
</div>
<div class="register-btn-container">
<button type="submit" id="register-btn" class="btn btn-default">注册</button>
</div>
</form>
</div>
</div>
<div class="col-md-4"></div>
</div>
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="../node_modules/jquery/dist/jquery.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="../node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<script>
$('#register-btn').click(function (e) {
// 阻止表单的默认行为
e.preventDefault()
// 使用jq获取表单数据
const formData = $('#register-form').serialize()
// console.log(formData) // user_name=12&user_account=12&user_password=12
$.ajax({
url:'/register',
method:'post',
data:formData
}).then(res=>{
console.log(res)
if (res.success){
alert('注册成功')
location.href = '/login'
}else {
alert(res.msg)
}
})
})
</script>
</body>
</html>
登录页
界面面展示
代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap 101 Template</title>
<!-- Bootstrap -->
<link href="../node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- HTML5 shim 和 Respond.js 是为了让 IE8 支持 HTML5 元素和媒体查询(media queries)功能 -->
<!-- 警告:通过 file:// 协议(就是直接将 html 页面拖拽到浏览器中)访问页面时 Respond.js 不起作用 -->
<!--[if lt IE 9]>
<script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
<![endif]-->
<style>
.register-container {
width: 80%;
border: 1px solid #e9e9e9;
margin: 150px auto;
padding: 20px 10%;
border-radius: 5px;
box-shadow: 5px 5px 5px 0 #e9e9e9;
}
.register-btn-container button{
width: 100%;
background: rgb(0, 220, 0);
}
</style>
</head>
<body>
<div class="row">
<div class="col-md-4"></div>
<div class="col-md-4">
<div class="register-container">
<form id="register-form">
<div class="form-group">
<label for="account">帐号</label>
<input type="text" name="user_account" class="form-control" id="account" placeholder="帐号">
</div>
<div class="form-group">
<label for="password">密码</label>
<input type="password" name="user_password" class="form-control" id="password" placeholder="密码">
</div>
<div class="register-btn-container">
<button type="submit" id="register-btn" class="btn btn-default">登录</button>
</div>
</form>
</div>
</div>
<div class="col-md-4"></div>
</div>
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="../node_modules/jquery/dist/jquery.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="../node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<script>
$('#register-btn').click(function (e) {
// 阻止表单的默认行为
e.preventDefault()
// 使用jq获取表单数据
const formData = $('#register-form').serialize()
// console.log(formData) // user_name=12&user_account=12&user_password=12
$.ajax({
url:'/login',
method:'post',
data:formData
}).then(res=>{
console.log(res)
if (res.success){
alert('登录成功')
location.href = '/'
}else {
alert(res.msg)
}
})
})
</script>
</body>
</html>
登陆后的页面
界面展示
代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap 101 Template</title>
<!-- Bootstrap -->
<link href="../node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- HTML5 shim 和 Respond.js 是为了让 IE8 支持 HTML5 元素和媒体查询(media queries)功能 -->
<!-- 警告:通过 file:// 协议(就是直接将 html 页面拖拽到浏览器中)访问页面时 Respond.js 不起作用 -->
<!--[if lt IE 9]>
<script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
<![endif]-->
</head>
<body>
<h1>你好</h1>
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="../node_modules/jquery/dist/jquery.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="../node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
</body>
</html>
后台代码
入口函数代码
由于入口函数的代码应该尽量简洁,所把路由封装到单独的js文件中
const express = require('express')
const router = require('./router')
const bodyParser = require('body-parser')
const session = require('express-session')
const app = new express()
// express本身没有session功能
//使用第三方中间件 express-session
// 配置要卸载路由之前
// 通过req.session.属性 = ?? 保存数据
// req.session.属性 获取数据
app.use(session({
secret:'userLogin',
resave:false,
saveUninitialized:true
}))
app.use(bodyParser.urlencoded({extended: false}))
app.use(bodyParser.json())
// 把模板引擎加载到express
app.engine('html', require('express-art-template'))
// 处理静态文件
app.use('/node_modules/', express.static('./node_modules/'))
app.use(router)
app.listen(3000, () => {
console.log('启动成功 127.0.0.1:3000')
})
路由代码
将保存,查询操作保存在user.js文件中 路由只需要导入调用即可
const express = require('express')
const user = require('./user')
const md5 = require('blueimp-md5')
// 创建路由容器
const router = express.Router()
// 挂载路由
router.get('/register', function (req, res) {
res.render('./register.html')
})
router.post('/register', function (req, res) {
console.log(req.body)
user.findOne(req.body).then((data) => {
if (data.length > 0) {
return res.send({
success: false,
msg: '注册失败,帐号已存在'
})
}
user.save(req.body).then(() => {
res.send({
success: true,
msg: '注册成功'
})
}).catch((err) => {
console.log(err)
})
}).catch((err) => {
console.log(err)
})
})
router.get('/login', function (req, res) {
res.render('./login.html')
})
router.post('/login', function (req, res) {
req.body.user_password = md5(req.body.user_password)
user.findOne(req.body).then(data => {
if (data.length > 0) {
if (data[0].user_password == req.body.user_password) {
// 设置cookie时间
var hour = 3600000
req.session.cookie.expires = new Date(Date.now() + hour)
req.session.cookie.maxAge = hour
req.session.isLogin = true
return res.send({
success: true,
msg: '登录成功'
})
}
return res.send({
success: false,
msg: '登录失败,请检查帐号密码是否正确'
})
}
})
})
router.get('/logout', function (req, res) {
res.render('./login.html')
})
router.get('/', function (req, res) {
console.log(req.session)
if (req.session.isLogin) {
res.render('./index.html')
} else {
res.render('./login.html')
}
})
// 导出
module.exports = router
user.js的代码
在user.js中进行数据库操作
const mysql = require('mysql');
const md5 = require('blueimp-md5')
// npm i blueimp-md5 安装加密插件
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '123456',
database: 'user'
});
connection.connect();
/**
* 保存帐号
*/
exports.save = function (user) {
user.user_password = md5(user.user_password)
return new Promise((resolve,reject)=>{
connection.query(`INSERT INTO USERS (user_name,user_account,user_password) value ('${user.user_name}','${user.user_account}','${user.user_password}')`, function (err, res, fields) {
if (err) {
// 发生错误的时候执行reject
reject(err)
}else {
resolve(res)
}
});
})
}
/**
* 查找一个帐号
*/
exports.findOne = function (user) {
const where = []
// 动态拼接字符串
if(user.user_account){
where.push(` and user_account = '${user.user_account}'`)
}
return new Promise((resolve,reject)=>{
// where.join('')将where使用''包起来
connection.query(`SELECT * FROM USERS WHERE 1 = 1 ${where.join('')}`, function (err, res, fields) {
if (err) {
// 发生错误的时候执行reject
reject(err)
}else {
resolve(res)
}
});
})
}