之前我们学了路由,数据库,加密等知识,那么这次我们就来综合的使用一下这些知识提高一下自己,我们可以做一个用户登录注册页面,将数据存储到数据库中,当然我们需要对我们输入的内容和数据库中的内容进行对比判断,然后决定存储或者返回数据;
我们先分析一下后台是如何处理数据的,拿到表单数据,里面含有用户名、密码等数据,结合服务器,使用各种路由和方法来处理我们提交的表单数据进行验证和插入操作,话不多说,现在开始,代码比较长,所以我们分几期来写:
1、我们首要的创建一个服务器:
//1.1 导入模块并且创建一个服务器在3007
const express = require('express')
const router = require('./Touters/User')
const app = express()
//1.3 不要忘记解析数据模块
app.use(express.urlencoded({extended:false}))
//7.1 代码冗余需要挂载优化中间件,放最前面
app.use((req,res,next)=>{
//7.2 挂载一个函数在res上面,接下来我们判断数据的时候直接调用这个函数就可以了
res.cc = (err,status = 1)=>{
//7.3 我们如果错误可以用字符串代替说明就一个字符串,如果不是就是一个对象,需要调用方法提示
res.send({
status,
message:err instanceof Error?err.message:err
})
}
next()
})
//1.2 我们将路由模块挂载到我们的服务器上
app.use('/api',router)
app.listen(3007,()=>{
console.log('server running at http://127.0.0.1:3007')
})
我们使用的端口是3007,创建一个服务器相信大家都会了,这里我们创建一个路由模块,为了实现模块,我们将各种处理数据的模块分开来,路由模块、数据库模块、服务器,模块,而路由模块又分出了一个路由处理函数模块,
const router = require('./Touters/User')
2、这是我们导入的自定义的路由模块:
//2.1 创建一个路由文件夹,然后挂载自己需要的路由
const express = require('express')
const harder = require('../Touters-harder/User-header')
//2.3 获取一个路由对象,注意是大写的R
const router = express.Router()
//2.2 注册一个路由用来注册用户
router.post('/requser',harder.reguser)
//2.4 注册一个路由来用户登录
router.post('/login',harder.login)
module.exports=router
3、这里挂载了两个路由,一个是注册、一个是登录,而在这个模块我们又导入了一个自定义模块,都封装了一些方法,这些是处理路由的方法的,是对用户提交表单数据的查询、插入等操作:
//3.1 创建一个处理函数文件夹,我们需要将路由和处理函数分离开来;
//3.2 用户注册处理函数
const index = require('../Db/index')
//5.1 既然我们提交的时候用户名和密码,所以需要我们加密操作
//5.2 先安装和导入加密模块
const bcry = require('bcryptjs')
//注意我们没写完一个函数对象需要暴露出去,我们可以直接使用exports来写
exports.reguser = (req,res)=>{
//3.4 我们对用户提交的表单进行数据合法判断
if(!req.body.username || !req.body.password){
return res.cc('数据不合法')
/*res.send({
status:1,
message:'数据不合法'
})*/
}
//3.5 对数据存在的判断
index.query(`SELECT * FROM ev_users WHERE username = '${req.body.username}'`,(err,results)=>{
if(err){
console.log(err.message)
}
//3.6 如果结果集长度大于0,说明数据存在,我们提示用户已存在
console.log(results)
//5.3 我们可以使用加密模块的hashsync方法进行加密
//该方法含有两个参数,第一个是需要我们加密的字符串,后面是一个加密等级,越高越复杂
req.body.password = bcry.hashSync(req.body.password,10)
if(results.rowsAffected > 0){
return res.cc('用户已存在')
/*res.send({
status:1,
message:'用户已存在',
})*/
}
//6.1 如果没有重复的话,我们就要进行数据插入了
const strsql = `INSERT INTO ev_users VALUES('${req.body.username}','${req.body.password}','NULL','NULL','NULL')`
index.query(strsql,(err,results)=>{
//6.2 判断是否出错
if(err){return console.log(err.message)}
if(results.rowsAffected >= 1){
return res.cc('用户注册成功',200)
/*res.send({
status:'200',
message:'用户注册成功'
})*/
}
})
})
}
//3.3 用户登录处理函数
exports.login = (req,res)=>{
res.send('用户登录函数')
}
我们提交数据后,需要在注册路由的处理函数里里面编写处理逻辑,先连接到数据库,我们先在数据库中创建好一个表:
这个表按照图中创建即可,由于需要对密码或者其他数据进行解密操作,可能比较长所以取大最大字符串范围,名字就取ev_users;
4、 链接数据库就需要用到数据库模块了:
//4.1 创建一个连接数据库的模块,不过我们先在数据库中创建一个用户表,记得安装
const mssql = require('mssql')
const dbconfig = {
user: 'sa',
password: '2783394007',
server: 'localhost',
database: 'MytestDatabase',
connectionTimeout: 120000,
requestTimeout: 3000000,
retryTimes: 3,
port: 1433,
options: {
encrypt: false
},
pool: {
max: 1024,
min: 1,
idleTimeoutMillis: 30000
}
}
//4.2 在数据库连接池中开设一个连接
const conn=new mssql.ConnectionPool(dbconfig,(err)=>{
if(err){return console.log(err)}
console.log('连接成功')})
//4.3 使用这个连接conn获取数据处理对象,暴露出去进行数据处理
const datadeal = new mssql.Request(conn)
module.exports = datadeal
这些我们之前都写过,现在就是拿来用的时候了,先看看现在项目的结构:
很明显的可以看到很显眼的三个文件夹,db、Touters、Touters_header,这些分别放着不同的处理模块,index就是数据库模块;
5、注册数据的处理:
回到我们的注册函数这一块,就是:
const index = require('../Db/index')
//5.1 既然我们提交的时候用户名和密码,所以需要我们加密操作
//5.2 先安装和导入加密模块
const bcry = require('bcryptjs')
//注意我们没写完一个函数对象需要暴露出去,我们可以直接使用exports来写
exports.reguser = (req,res)=>{
//3.4 我们对用户提交的表单进行数据合法判断
if(!req.body.username || !req.body.password){
return res.cc('数据不合法')
/*res.send({
status:1,
message:'数据不合法'
})*/
}
//3.5 对数据存在的判断
index.query(`SELECT * FROM ev_users WHERE username = '${req.body.username}'`,(err,results)=>{
if(err){
console.log(err.message)
}
//3.6 如果结果集长度大于0,说明数据存在,我们提示用户已存在
console.log(results)
//5.3 我们可以使用加密模块的hashsync方法进行加密
//该方法含有两个参数,第一个是需要我们加密的字符串,后面是一个加密等级,越高越复杂
req.body.password = bcry.hashSync(req.body.password,10)
if(results.rowsAffected > 0){
return res.cc('用户已存在')
/*res.send({
status:1,
message:'用户已存在',
})*/
}
//6.1 如果没有重复的话,我们就要进行数据插入了
const strsql = `INSERT INTO ev_users VALUES('${req.body.username}','${req.body.password}','NULL','NULL','NULL')`
index.query(strsql,(err,results)=>{
//6.2 判断是否出错
if(err){return console.log(err.message)}
if(results.rowsAffected >= 1){
return res.cc('用户注册成功',200)
/*res.send({
status:'200',
message:'用户注册成功'
})*/
}
})
})
}
我们导入数据库模块和一个加密模块,
const bcry = require('bcryptjs')
加密模块是用来加密密码的,使用它的一个加密方法
req.body.password = bcry.hashSync(req.body.password,10)
这个是将用户提交的表单密码加密,第一个参数就是加密的密码,第二个参数是加密的等级,等级越高,加密后的字符串就会越复杂,所以我们设置一个10就可以,加密后重新赋值给挂载的对象密码;
在拿到数据之后,我们先要判断用户提交数据是否合理,我们先判断一下是否为空:
//3.4 我们对用户提交的表单进行数据合法判断
if(!req.body.username || !req.body.password){
return res.cc('数据不合法')
/*res.send({
status:1,
message:'数据不合法'
})*/
}
这里的res.cc()其实就是我们在服务器挂载的一个简化代码的函数,我们可以通过这个函数和参数来代替下面注释代码的部分,这可以减少不少冗余的代码,我们来分析一下,如果提交数据不合法,我们就通过res.send()给用户返回出去,一个状态和一个消息:
//7.1 代码冗余需要挂载优化中间件,放最前面
app.use((req,res,next)=>{
//7.2 挂载一个函数在res上面,接下来我们判断数据的时候直接调用这个函数就可以了
res.cc = (err,status = 1)=>{
//7.3 我们如果错误可以用字符串代替说明就一个字符串,如果不是就是一个对象,需要调用方法提示
res.send({
status,
message:err instanceof Error?err.message:err
})
}
next()
})
这个简化方法含有两个参数,一个是错误对象,也可能是错误信息,所以我们通过instaceof这个方法来判断这个对象是否是对象,如果是,我们返回message属性即可,如果是字符串,直接返回就行,既然是中间件,就不要忘了next,而且需要放在所有中间件之前;
6、再来看看我们的数据库操作:
//3.5 对数据存在的判断
index.query(`SELECT * FROM ev_users WHERE username = '${req.body.username}'`,(err,results)=>{
if(err){
console.log(err.message)
}
//3.6 如果结果集长度大于0,说明数据存在,我们提示用户已存在
console.log(results)
//5.3 我们可以使用加密模块的hashsync方法进行加密
//该方法含有两个参数,第一个是需要我们加密的字符串,后面是一个加密等级,越高越复杂
req.body.password = bcry.hashSync(req.body.password,10)
if(results.rowsAffected > 0){
return res.cc('用户已存在')
/*res.send({
status:1,
message:'用户已存在',
})*/
}
//6.1 如果没有重复的话,我们就要进行数据插入了
const strsql = `INSERT INTO ev_users VALUES('${req.body.username}','${req.body.password}','NULL','NULL','NULL')`
index.query(strsql,(err,results)=>{
//6.2 判断是否出错
if(err){return console.log(err.message)}
if(results.rowsAffected >= 1){
return res.cc('用户注册成功',200)
/*res.send({
status:'200',
message:'用户注册成功'
})*/
}
})
})
我们用的是mssql模块,也就是sql server,其他数据库也一样,只是sql语句和results会有些不一样,但是学过相关数据库知识的应该改起来不会困难;
在拿到数据之后,且数据是合法的,那就开始判断是否在数据库中存在,
我们已经生成了一些数据,可以看到除了第一个记录,其他记录的密码都是加密后的,通过查询语句,将提交过来的用户名进行查询,如果没有的话, results.rowsAffected就会等于0,如果有的话就会大于0,所以在大于0的时候,对他进行用户存在处理,这里返回了一个数据:
提交数据相信大家都会,点击Body然后按照表中的列名填写数据,如果数据存在的话,就会拿到用户存在的信息,我们同样使用简化代码的这个自定义cc()函数:
return res.cc('用户已存在')
如果用户不存在,那么就可以开始我们的插入操作了,就相当于我们注册了一个用户,插入数据的话,使用数据库模块的query()函数就可以,大同小异,这个数据库模块其实就是一个连接数据的处理对象,所以可以直接对数据库表操作:
//4.3 使用这个连接conn获取数据处理对象,暴露出去进行数据处理
const datadeal = new mssql.Request(conn)
module.exports = datadeal
是我们通过数据库模块从数据库连接池里面获取的连接对象的一个处理对象,通过exports暴露出去了;
因为前面判断的问题排除了,那么我们就直接插入就可以,当然不同数据库就要用不同的sql插入语言,同样使用rowsAffected这个属性判断是否成功,如果大于等于1说明成功可,通过cc()方法返回,不过这里第二参数就是200,表明是一个成功的状态,当然,我们使用cc()这个方法是默认的状态是一个失败的状态1;
res.cc = (err,status = 1)=>
所以我们直接改了:
return res.cc('用户注册成功',200)
这个一个查询的结果,我们可以看到列名和属性,后面还有一个rowsAffected很清楚的表示1;
好了,一期不能太长,就到这吧,现在我们可以通过提交表单来对数据库进行插入操作,也就是实现了一个注册的功能了,还是挺简单的,就是写路由,路由方法,中间件,加密,判断合法什么的,比较简单,但是内容多很容易无从下手,所以我们需要模块化,在路由模块里面挂载一个登录一个注册路由,然后通过exports将路由暴露出去,到服务器里面,使用use挂载一下路由就可以了;