这是我参与2022首次更文挑战的第3天,活动详情查看:2022首次更文挑战
前言
最近我总结了一下我们做项目经常要制作的login页面,完成登录和注册的功能。今天小编就以express+mongoose来举例,实现相应功能。让我们一起跟着我看看吧。
步骤
1.先用express搭建一个服务器(app.js),下载相应包,并配置相应配置。
我用的模板引擎是ejs,以html为后缀,相应的配置是:
//配置模板引擎
app.engine('.html', ejs.renderFile)
app.set('view engine', 'ejs')
第三方中间是body-parser,相应的配置是:
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
当然登录注册肯定要用到session,可以用来保存验证码内容以及限制路由决定是否放行。 我用的包的是express-session,相应配置和注释以下:
app.use(session({
secret: 'this is session', //服务器端生成session
name: "redspider", //修改session对应的cookie的名称
resave: false, //强制保存session即使它没有改变
saveUninitialized: true, //强制保存未保存的session
cookie: {
maxAge: 1000 * 60 * 60 * 24,
secure: false //true表示只有https才能访问cookie
},
rolling: true //每次请求时强行设置cookie,这将重置cookie的过期时间
}))
app.js的配置如下:
const express = require('express');
const app = express();
const bodyParser = require('body-parser')
const ejs = require('ejs')
const session = require('express-session')
//引入路由模块
const admin = require('./routes/admin')
//配置模板引擎
app.engine('.html', ejs.renderFile)
app.set('view engine', 'ejs')
//配置静态web目录
app.use(express.static("static"))
//第三方中间件获取post提交数据
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(session({
secret: 'this is session', //服务器端生成session
name: "redspider", //修改session对应的cookie的名称
resave: false, //强制保存session即使它没有改变
saveUninitialized: true, //强制保存未保存的session
cookie: {
maxAge: 1000 * 60 * 60 * 24,
secure: false //true表示只有https才能访问cookie
},
rolling: true //每次请求时强行设置cookie,这将重置cookie的过期时间
}))
//配置路由模块
app.use('/admin', admin)
//监听端口
app.listen(3000, () => {
console.log('server is running');
})
2.配置路由模块
app.js的配置路由:
引入admin 路由,
app.use('/admin', admin)
在admin.js中admin再挂载的路由是login:
引入login模块,
router.use('/login', login)
注意:要是你单纯的制作登录注册页面,不需要嵌套这么多层,我这里是还有其他功能。
admin.js配置如下:
const express = require('express')
const router = express.Router()
const url = require("url")
//引入模块
const manager = require('./admin/manager')
const login = require('./admin/login')
//挂载路由
router.use('/manager', manager)
router.use('/login', login)
module.exports = router
login.js的配置如下:
const express = require('express');
const router = express.Router();
const svgCaptcha = require('svg-captcha');
const ManagerModel = require('../../model/mangerModel')
const md5 = require('md5');
//登录模块
router.get('/', (req, res) => {
res.send("登录")
})
//退出登录
router.get('/loginout', (req, res) => {
res.send("loginout")
})
//验证码
router.get('/verify', async(req, res) => {
res.send("verify")
})
//注册模块
router.post('/register', async(req, res) => {
res.send("register")
})
//登录表单提交的数据
router.post('/dologin', async(req, res) => {
res.send("dologin")
})
module.exports = router
这里login页面的路由分别对应登录,退出登录,注册,还有验证码。
3.login.js配置的路由实现相应功能。
当路由是/admin/login时,我们通过ejs模板引擎渲染(login.html)登录界面。 login.html:
<body>
<!-- login area start -->
<div class="login-register-area pt-100px pb-100px">
<div class="container">
<div class="row">
<div class="col-lg-7 col-md-12 ml-auto mr-auto">
<div class="login-register-wrapper">
<div class="login-register-tab-list nav">
<a class="active" data-bs-toggle="tab" href="#lg1">
<h4>login</h4>
</a>
<a data-bs-toggle="tab" href="#lg2">
<h4>register</h4>
</a>
</div>
<div class="tab-content">
<div id="lg1" class="tab-pane active">
<div class="login-form-container">
<div class="login-register-form">
<form action="/admin/login/dologin" method="post">
<input type="text" name="username" placeholder="Username" id="username" />
<input type="password" name="password" placeholder="Password" id="password" />
<div>
<input type="captcha" id="verify" name="verify" placeholder="captcha" width="100px" />
<img src="/admin/login/verify" title="看不清,点击刷新" onclick="javascript:this.src='/admin/login/verify?mt='+Math.random()">
</div>
<div class="button-box">
<div class="login-toggle-btn">
<input type="checkbox" />
<a class="flote-none" href="javascript:void(0)">Remember me</a>
<a href="#">Forgot Password?</a>
</div>
<button type="submit"><span>Login</span></button>
</div>
</form>
</div>
</div>
</div>
<div id="lg2" class="tab-pane">
<div class="login-form-container">
<div class="login-register-form">
<form action="/admin/login/register" method="post">
<input type="text" name="username" placeholder="Username" />
<input type="password" name="password" placeholder="Password" />
<input placeholder="Email" type="email" name="email" />
<div class="button-box">
<button type="submit"><span>Register</span></button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- login area end -->
<script src="/login/js/vendor/vendor.min.js"></script>
<script src="/login/js/plugins/plugins.min.js"></script>
<!-- Main Js -->
<script src="/login/js/main.js"></script>
</body>
首先讲一讲登录功能
然后通过表单提交post方法提交数据,action对应相应的路由,action="/admin/login/dologin",输入框对应name来获取值,在login.js中相应的路由,通过req.body.username和req.body.password来获取用户名和密码。
然后就是验证码,我用到的包是svg-captcha,生成相应的验证码,同时把验证码文本保存在session中,相应的配置如下:
const svgCaptcha = require('svg-captcha');
router.get('/verify', async(req, res) => {
var captcha = svgCaptcha.create();
req.session.captcha = captcha.text;
res.type('svg');
res.status(200).send(captcha.data);
// console.log(req.session.captcha);
})
我也做了一个点击刷新的功能,如下:
<img src="/admin/login/verify" title="看不清,点击刷新" onclick="javascript:this.src='/admin/login/verify?mt='+Math.random()">
最后就是通过获取的用户名和密码去数据库中查找是否有匹配的collection,如果有匹配,而且验证码正确,则登录成功。当然在此之前,你也可以做一些前台验证来限制它们的规范,这里也要将匹配的collection保存在cookie中。
还有比较重要的一点是:通过session来限制路由的放行,当服务器中没有相应cookie时,则不能放行。 相应在admin.js配置如下
//限制没有session不放行
router.use((req, res, next) => {
const myURL = new URL(req.url, 'http://127.0.0.1:3000/');
let pathname = myURL.pathname;
// console.log(pathname);
if (req.session.userinfo && req.session.userinfo.username) {
next()
} else {
if (pathname == "/login" || pathname == "/login/dologin" || pathname == "/login/register" || pathname == "/login/verify") {
next()
} else {
res.redirect("/admin/login")
}
}
})
这里提一下退出登录,就是将页面跳转至login界面,同时将session中的数据清除。 如下:
router.get('/loginout', (req, res) => {
req.session.userinfo = null;
res.redirect("/admin/login")
})
4.mongoose操作数据库 上面也提到要在数据库中匹配数据以及添加数据,我们当然要对mongoose进行一下封装: 我们建立一个文件夹model,封装mongoose
(1)、我们与数据库建立连接:在core.js中配置:
const mongoose = require('mongoose');
const config = require('../config/config')
mongoose.connect(config.dburl, { useNewUrlParser: true, useUnifiedTopology: true }, function(err) {
if (err) {
console.log(err);
return
}
console.log('连接成功');
})
module.exports = mongoose;
(2)、引入core.js,通过schema规范数据,利用模型来操作数据库,在managermodel.js配置:
const mongoose = require('./core')
let ManagerSchema = mongoose.Schema({
username: { type: String },
password: { type: String },
email: { type: String },
mobile: { type: String },
status: { type: Number },
login_time: { type: Number },
add_time: { type: String },
})
module.exports = mongoose.model('Manager', ManagerSchema, 'manager')
(3)、在login.js引入managermodel.js,在相应路由中完成对应功能。 登录和注册功能如下:
//登录
router.post('/dologin', async(req, res) => {
let username = req.body.username
let password = req.body.password
let verify = req.body.verify
// console.log(verify);
// console.log(req.session.captcha.toLowerCase());
//1.判断验证码是否正确
if (verify.toLowerCase() != req.session.captcha.toLowerCase()) {
res.render("admin/pubic/error.html", {
"redirectUrl": "/admin/login",
"message": "图形验证码输入错误"
})
return
}
//2.判断用户名是否正确
let result = await ManagerModel.find({
"username": username,
"password": md5(password)
})
// console.log(result);
if (result.length > 0) {
//保存用户信息
req.session.userinfo = result[0];
//登录成功
res.render("admin/pubic/success.html", {
"redirectUrl": "/admin/manager",
"message": "登录成功"
})
} else {
res.render("admin/pubic/success.html", {
"redirectUrl": "/admin/login",
"message": "用户名或密码错误"
})
}
//注册
router.post('/register', async(req, res) => {
let username = req.body.username
let password = req.body.password
let email = req.body.email
let result = await ManagerModel.find({
"username": username,
"password": md5(password)
})
if (result.length > 0) {
res.send("用户已存在")
} else {
var newuser = new ManagerModel({
"username": username,
"password": md5(password),
"email": email
})
await newuser.save()
res.redirect("/admin/login")
}
})
})
注册功能也是和登录一样,只是我们在数据库中保存数据。
下面我讲login.js的配置完整呈现:
const express = require('express');
const router = express.Router();
const svgCaptcha = require('svg-captcha');
const ManagerModel = require('../../model/mangerModel')
const md5 = require('md5');
//登录模块
router.get('/', (req, res) => {
res.render("admin/login/login.html")
// res.send("登录")
})
//退出登录
router.get('/loginout', (req, res) => {
req.session.userinfo = null;
res.redirect("/admin/login")
})
//验证码
router.get('/verify', async(req, res) => {
var captcha = svgCaptcha.create();
req.session.captcha = captcha.text;
res.type('svg');
res.status(200).send(captcha.data);
// console.log(req.session.captcha);
})
//注册模块
router.post('/register', async(req, res) => {
let username = req.body.username
let password = req.body.password
let email = req.body.email
let result = await ManagerModel.find({
"username": username,
"password": md5(password)
})
if (result.length > 0) {
res.send("用户已存在")
} else {
var newuser = new ManagerModel({
"username": username,
"password": md5(password),
"email": email
})
await newuser.save()
res.redirect("/admin/login")
}
})
//登录表单提交的数据
router.post('/dologin', async(req, res) => {
let username = req.body.username
let password = req.body.password
let verify = req.body.verify
// console.log(verify);
// console.log(req.session.captcha.toLowerCase());
//1.判断验证码是否正确
if (verify.toLowerCase() != req.session.captcha.toLowerCase()) {
res.render("admin/pubic/error.html", {
"redirectUrl": "/admin/login",
"message": "图形验证码输入错误"
})
return
}
//2.判断用户名是否正确
let result = await ManagerModel.find({
"username": username,
"password": md5(password)
})
// console.log(result);
if (result.length > 0) {
//保存用户信息
req.session.userinfo = result[0];
//登录成功
res.render("admin/pubic/success.html", {
"redirectUrl": "/admin/manager",
"message": "登录成功"
})
} else {
res.render("admin/pubic/success.html", {
"redirectUrl": "/admin/login",
"message": "用户名或密码错误"
})
}
})
module.exports = router
总结一下:登录和注册相对来说步骤比较简单,也是新手比较容易上手的内容,多想想逻辑思维,多贯通,一步步来,加油!