基于Nodejs+mysql+html实现登录注册功能模块

一.基于Nodejs+mysql+html实现登录注册功能模块实现思路

1. 环境搭建

  • 安装 Node.js: 确保你的开发环境中已经安装了 Node.js。
  • 创建项目目录: 创建一个新的项目目录,并在该目录中初始化一个新的 Node.js 项目。
  • 安装依赖: 使用 npm 安装必要的依赖包,如 Express(一个流行的 Node.js Web 应用框架)、mysql(数据库)、bcrypt(密码加密库)等。

2. 设计数据库模型

  • 选择数据库: 你可以选择任何支持 Node.js 的数据库,比如 mysql。
  • 设计用户模型: 用户模型至少应该包括用户名、密码等字段。

3. 设置服务器

  • 安装 Express: 使用 npm 安装 Express。
  • 创建服务器: 使用 Express 创建一个基本的 HTTP 服务器。

4. 创建登录和注册页面

  • HTML 页面: 创建登录和注册的 HTML 表单页面。
  • 路由: 使用 Express 设置路由来处理登录和注册的请求。

5. 处理表单提交

  • 密码加密: 使用 bcrypt 对用户密码进行哈希处理,以增强安全性。
  • 存储用户: 将经过验证的用户数据存储到数据库中。
  • 处理登录: 检查用户名和密码是否匹配数据库中的记录。

二.后端具体实现步骤

1.初始化项目

1.1.创建项目

  • 新建 node_api 文件夹作为项目根目录,并在项目根目录中打开cmd或PowerShell运行如下的命令,初始化包管理配置文件: 
    npm init -y
  • 运行如下的命令,安装 express框架:
    npm i express
  • vscode打开项目,在项目根目录中新建 app.js 作为整个项目的入口文件,并初始化如下的代码:
    // 导入express
    const express = require('express')
    // 创建express实例
    const app = express()
    
    
    // 启动服务器
    app.listen(3000, () => {
        console.log('server running at http://localhost:3000')
    });
1.2.配置cors跨域 
  • 运行如下的命令,安装cros中间件:
    npm i cors
  • 在 app.js 中导入并配置 cors 中间件:
    //注册跨域中间件
    const cors = require('cors')
    app.use(cors())
1.3. 配置解析表单数据的中间件 
  • 配置解析 application/x-www-form-urlencoded 格式的表单数据的中间件:

    extended: false 表示使用简化的 URL 编码解析器,它只能解析键值对,并且每个键只能有一个值。这意味着如果表单中有重复的字段名,只有最后一个会被解析并保存。如果extended: true,那么会使用一个更为灵活的解析器,它可以解析嵌套的对象(例如,a[b][c]=d 这样的键),并且可以处理重复的字段名,将它们作为一个数组来保存。

  • // 注册解析表单数据的中间件
    app.use(express.urlencoded({extended:false}))
1.4. 创建路由相关的文件夹
  • 在项目根目录下,新建 router 文件夹,用来存放所有的路由模块,路由模块中,只存放客户端的请求与处理函数之间的映射关系
  • 在项目根目录中,新建 router_handler 文件夹,用来存放所有的路由处理函数模块,路由处理函数模块中,专门负责存放每个路由对应的处理函数
1.5.初始化路由 
  • 在 router 文件夹中,新建 user.js 文件,作为用户的路由模块
    // 引入express
    const express = require('express');
    // 创建用户模块
    const router = express.Router();
    
    // 注册
    router.post('/register', (req,res)=>{
        res.send('注册成功')
    });
    // 登录
    router.post('/login', (req,res)=>{
        res.send('登录成功')
    });
    // 导出路由
    module.exports = router;
  • 在app.js内导入并使用用户路由模块
      // 导入用户路由模块
    const routeruser = require('./router/use')
    app.use('/api',routeruser)
    1.7. 将路由模块中的处理函数抽离出来
  • router_handler文件夹中,新建 userhandle.js 文件,作为用户的路由处理函数模块
    /*
     * 在这里定义和用户相关的路由处理函数,供 /router/user.js 模块进行调用
     */
    // 用户注册处理函数
    exports.register = (req, res) => {
        res.send('注册成功')
    }
    // 用户登录处理函数
    exports.login = (req, res) => {
        res.send('登录成功')
    }
  • 在  /router/user.js 中/router_handler/userhandle.js ,并调用对应的处理函数
    // 引入express
    const express = require('express');
    // 创建用户模块
    const router = express.Router();
    
    // 导入用户处理函数
    const routerhandle = require('../routerhandle/userhandle');
    
    // 注册
    router.post('/register', routerhandle.register);
    // 登录
    router.post('/login', routerhandle.login);
    // 导出路由
    module.exports = router;
    2.具体实现登录注册代码
2.1.新建user数据表

 

2.2. 安装并配置mysql
  • 运行如下命令,安装 mysql 模块:
    npm i mysql
  • 在项目根目录中新建/db/index.js文件,并创建数据库的连接对象:

2.3. 安装并导入用户密码加密依赖
  • 运行如下命令,安装 bcryptjs 依赖:
    npm i bcryptjs@2.4.3
2.4. 注册模块处理函数完整代码
// 引入数据库
const mysql = require('../db/mysql')
//导入bcryptjs加密库
const bcrypt = require('bcryptjs')

// 注册
exports.register = (req, res) => {
    // 获取客户端提交到服务器的用户信息
    const userinfo = req.body;
    // 判断用户名密码是否为空
    if (!userinfo.username || !userinfo.password) {
        return res.send({
            code: 1,
            msg: '用户名或密码不能为空'
        })
    }
    // 查询用户名是否被占用
    const registermysql = "select * from node_use where username = ?"
    mysql.query(registermysql, userinfo.username, (err, result) => {
        if (err) {
            return res.send({
                code: 1,
                msg: err.message
            })
        }
        if (result.length > 0) {
            return res.send({
                code: 1,
                msg: '用户名已存在'
            })
        }
        // 对密码进行加密
        userinfo.password = bcrypt.hashSync(userinfo.password, 10)
        // 插入数据
        const regmysql = "insert into node_use set ?"
        // 执行sql语句
        mysql.query(regmysql, { username: userinfo.username, password: userinfo.password }, (err, result) => {
            if (err) {
                res.send({
                    code: 1,
                    mes: err.message
                })
            }
            res.send({
                code: 0,
                msg: '注册成功'
            })
        })

    })
}
2.5. 安装生成 Token 字符串的包
  • 运行如下命令,安装生成 Token 字符串的包
    npm i jsonwebtoken
2.6. 登录模块处理函数完整代码
// 引入数据库
const mysql = require('../db/mysql')
//导入bcryptjs加密库
const bcrypt = require('bcryptjs')
// 导入jwt
const jwt = require('jsonwebtoken')


exports.login = (req, res) => {
    // 获取客户端提交到服务器的用户信息
    const logininfo = req.body;
    // 判断用户名密码是否为空
    if (!logininfo.username || !logininfo.password) {
        return res.send({
            code: 1,
            msg: '用户名或密码不能为空'
        })
    }
    // 查询用户名是否被占用
    const loginmysql = "select * from node_use where username = ?"
    // 执行sql语句
    mysql.query(loginmysql, logininfo.username, (err, result) => {
        if (err) {
            return res.send({
                code: 1,
                msg: err.message
            })
        }
        if (result.length !== 1) {
            return res.send({
                code: 1,
                msg: '用户名不存在'
            })
        }
        // 判断密码是否正确
        const compareResult = bcrypt.compareSync(logininfo.password, result[0].password)
        if (!compareResult) {
            return res.send({
                code: 1,
                msg: '密码错误'
            })
        }
        // 剔除user中的password属性
        const user = { ...result[0], password: '' }
        // 生成token
        const tokenStr = jwt.sign(user, 'safsaf')
        res.send({
            code: 0,
            msg: '登录成功',
            token: tokenStr
        })

    }
    )
}
 2.7.配置解析token的中间件
  • 运行如下的命令,安装解析 Token的中间件
    // 注意这里必须加版本
    npm i express-jwt@5.3.3
    
  • 在 app.js 中注册路由之前,配置解析 Token 的中间件
    // 导入express-jwt
    const jwt = require('express-jwt')
    
    // 解析token的中间件
    app.use(jwt({secret:'safsaf'}).unless({path:['/api/login','/api/register']}))
    
    
    // unless({path:['/api/login','/api/register']})) 
    // 除了登录和注册之外的接口都需要验证身份
    
    // 必须写在导入路由模块之前
  • 在 app.js 中的 误级别中间件 里面,捕获并处理 Token 认证失败后的错误
    // 捕获身份认证失败的中间件
    app.use(function (err, req, res, next) {
        // 捕获身份认证失败的中间件
        if (err.name === "UnauthorizedError") {
          return res.send({
            code:1,
            msg:'身份认证失败'
          });
        }
      });
    
    // 必须写在导入路由模块之前

三.前端具体实现步骤

1.新建 html 文件夹作为项目根目录,并在项目根目录下创建login.html与register.html

注意

2.注册具体实现代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>注册</title>
    <style>
        .login {
            width: 50%;
            height: 400px;
            margin: 150px auto;
            background-color: rgb(212, 205, 205);
        }

        .name {
            width: 60%;
            height: 80px;
            margin: 10px auto;
            line-height: 80px;
        }

        .but {
            width: 25%;
            height: 50px;
            margin: 10px auto;
            line-height: 50px;
        }

        button {
            width: 80px;
            height: 40px;
            margin: 10px auto;
            background-color: rgb(102, 177, 255);
            border: none;
        }
    </style>
</head>

<body>
    <div class="login">
        <h1 style="text-align: center;padding-top: 30px;">欢迎注册</h1>
        <div class="name" style="margin-top: 60px;">
            <span style="margin-left: 10px;font-weight: 600;font-size: 20px;">用户名:</span>
            <input type="text" style="width: 70%;height: 50px;font-size: 18px;" id="username">
        </div>
        <div class="name">
            <span style="margin-left: 10px;font-weight: 600;font-size: 20px;">密 &nbsp;&nbsp;码:</span>
            <input type="password" style="width: 70%;height: 50px;font-size: 18px;" id="password">
        </div>
        <div class="but">
            <button style="float: left;" id="log">注册</button>
            <button style="float: right;" id="back">取消</button>
        </div>

    </div>
    </div>


    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script>
        // 注册按钮事件
        document.querySelector('#log').addEventListener('click', async () => {
            // 创建 XMLHttpRequest 对象
            var xhr = new XMLHttpRequest();
            // 请求方式以及url
            xhr.open('POST', 'http://localhost:3000/rest/register', true);
            // 将默认json格式转换为application/x-www-form-urlencoded格式
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            const params = new URLSearchParams();
            params.append("username", username.value);
            params.append("password", password.value);
            // 发送请求并携带参数
            xhr.send(params);
            // 请求监听
            xhr.addEventListener('loadend', () => {
                const data = JSON.parse(xhr.response)
                if (data.code === 0) {
                    alert(data.msg)
                    window.location.href = 'login.html'
                } else {
                    alert(data.msg)
                }
            })
        })

        // 取消按钮事件
        document.querySelector('#back').addEventListener('click', () => {
            window.location.href = 'login.html'
        })
    </script>
</body>

</html>
3.登录具体实现代码 
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录</title>
    <style>
        .login {
            width: 50%;
            height: 400px;
            margin: 150px auto;
            background-color: rgb(212, 205, 205);
        }

        .name {
            width: 60%;
            height: 80px;
            margin: 10px auto;
            line-height: 80px;
        }

        .but {
            width: 25%;
            height: 50px;
            margin: 10px auto;
            line-height: 50px;
        }

        button {
            width: 80px;
            height: 40px;
            margin: 10px auto;
            background-color: rgb(102, 177, 255);
            border: none;
        }
    </style>
</head>

<body>
    <div class="login">
        <h1 style="text-align: center;padding-top: 30px;">欢迎登录</h1>
        <div class="name" style="margin-top: 60px;">
            <span style="margin-left: 10px;font-weight: 600;font-size: 20px;">用户名:</span>
            <input type="text" style="width: 70%;height: 50px;font-size: 18px;" id="username">
        </div>
        <div class="name">
            <span style="margin-left: 10px;font-weight: 600;font-size: 20px;">密 &nbsp;&nbsp;码:</span>
            <input type="password" style="width: 70%;height: 50px;font-size: 18px;" id="password">
        </div>
        <div class="but">
            <button style="float: left;" id="log">登录</button>
            <button style="float: right;" id="reg">注册</button>
        </div>

    </div>
    </div>
    <script>
        // 登录按钮事件
        document.querySelector('#log').addEventListener('click', async () => {
            // 创建 XMLHttpRequest 对象
            var xhr = new XMLHttpRequest();
            // 请求方式以及url
            xhr.open('POST', 'http://localhost:3000/rest/login', true);
            // 设置请求头
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            // 将默认json格式转换为application/x-www-form-urlencoded格式
            const params = new URLSearchParams();
            params.append("username", username.value);
            params.append("password", password.value);
            // 发送请求并携带参数
            xhr.send(params);
            // 请求监听
            xhr.addEventListener('loadend', () => {
                const data = JSON.parse(xhr.response)
                if (data.code === 0) {
                    alert(data.msg)
                    window.location.href = 'index.html'
                } else {
                    alert(data.msg)
                }
            })
        })
        // 注册按钮事件
        document.querySelector('#reg').addEventListener('click', () => {
            window.location.href = 'register.html'
        })


    </script>
</body>

</html>

!!!前端发送网络请求部分使用的是原生Ajax,也可使用三方库axios

  • 23
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值