完成完整的登录和注册功能

864 阅读6分钟

这是我参与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

总结一下:登录和注册相对来说步骤比较简单,也是新手比较容易上手的内容,多想想逻辑思维,多贯通,一步步来,加油!