一、环境搭建
去官网 NodeJS下载,这个同时还附带好用的包管理器NPM,方便后续下载管理各种包。
一路安装完毕后,我们来创建自己的第一个应用。NodeJS是在服务器上执行的JS脚本,因此语法和原生JS一致,很方便上手。
二、创建应用
首先需要创建一个Main.js,这个是主文件,运行时需在CMD中运行 node main (注意,nodejs不含热更新,每次修改后需要结束命令后重新执行)
main.js
1 let config = require('./config') //这里引入数据库连接所需要的配置文件 2 const sql = require('mssql') //引入数据库模块,需要额外安装 3 let express = require('express') 4 let app = express() //引入创建express框架,创建服务,需额外安装 5 let bodyParser = require('body-parser') 6 let multer = require('multer') 7 let formData = multer() //中间件模块,能够解析前端传递过来的数据,需额外安装 8 const Login = require('./API/Login/Login') 9 const Asset = require('./API/Asset/GetList') //这里是传递的组件,如果有用vue开发的话,应该对这个引入方法不陌生(import变成require) 10 console.log(Asset.testFun('你好', '我的朋友')) 11 12 const appPool = new sql.ConnectionPool(config) //使用该配置,创建一个连接池 13 14 app.use(bodyParser.json()) //使用中间件进行数据解析 15 16 app.all('*', function (req, res, next) { 17 res.header('Access-Control-Allow-Origin', '*') //设置回应头,这里是允许跨域,所有IP均允许 18 res.header('Access-Control-Allow-Headers', 'content-type') 19 res.header('Access-Control-Allow-Methods', 'DELETE,PUT,POST,GET,OPTIONS') 20 if (req.method.toLowerCase() === 'options') res.sendStatus(200) 21 else next() 22 }) 23 24 app.post('/test', formData.array(), (req, res) => { 25 //req.body是前端获取到的数据,这里同样可以创建新的数据库连接 26 const testConn = new sql.ConnectionPool(testCon) 27 console.log(`${req.body.Age}`) 28 testConn.connect().then(pool => { 29 pool.query(`select ${req.body.Age}`).then(result => { 30 console.log(result.recordset) //recordset是获得的结果集,若是有多条查询语句,则只获得第一个。想要获取全部请用recordsets 31 }).catch(err => console.log(err)) 32 }).catch(Err => console.log(Err)) 33 }) 34 35 app.post('/Login', formData.array(), (req, res) => { 36 Login.Login(req, res) 37 }) 38 39 //创建成功后,在组件内调用数据库连接为 req.app.locals.db.query("……") 40 appPool.connect().then(function (pool) { 41 app.locals.db = pool 42 const server = app.listen(8081, '127.0.0.1', function () { 43 let host = server.address().address //这里因为是本机调试,因此监听的是本地地址。发布后请调整为服务器地址 44 let port = server.address().port 45 console.log("应用实例,访问地址为http://%s:%s", host, port) 46 }) 47 }).catch(err => console.log('连接到数据库失败', err)) 48
这是主文件,后续其余接口都在各自的js内编写然后在此处引入,并监听对应地址,调用指定模块。使用res.send(data)来给前端传递数据
三、存在的问题
1.Q:如何处理SQL注入问题? A:不需要!
该模块自带防注入功能。如果需要严谨,请用
1 req.app.locals.db.request() 2 .input('AgeQ', sql.Int, req.body.Age) 3 .input('UserNameQ', sql.VarChar, req.body.UserName) 4 .query('select * from UserInfo where Age = @AgeQ and UserName = @UserNameQ')
这里的input会严格控制输入参数的类型,若是不指定数据类型,则会自动变换。
但是它不会返回给你一个值让你知道这个参数合不合法。因此请酌情使用。
2.Q:如何处理参数缺省? A:循环判断。
缺省,也就是前端查询时未提供该条件(或者是传递空字符串),需要设定的默认参数。因为最终执行的语句是字符串,因此我们可以先做一个循环判断,最后拼接起来。
1 let sql = '' 2 for (let k in req.body) { 3 let str = (req.body[k] === '') ? '' : ' and ' + `${k} = ` + req.body[k] 4 sql += str 5 }
若该条件为空,则拼接'',否则拼接为一个查询条件。最终将其插入到查询语句中。此处用splice去除掉第一个'and'
1 let querySql = `select * 2 from TB_Asset 3 where ${sql.slice(4)} 4 order by OperationTime desc`
3.Q:字符串拼接会导致SQL注入,如何避免? A:没找到好办法。
网上用mysql的比较多,但也都没提到这类情况(大家都是sql数据库,用的都是js语法,架构应该大同小异,所以不至于存在什么独有的处理方法吧,大概)
就像上面说的,无论是直接query(……)执行,抑或是通过input的类型判断,只要是将参数直接传入到query方法中的话,mssql都会自行判断(譬如你传递一个 15 or 1=1,或者 15; drop database xxx)
会报错,并中断执行。
所以个人使用的是对传入字符串做判断 indexOF(' or') || indexOF(';') ,若是返回不为-1,则直接将该参数作空。因为大概sql注入就这两种情况吧。
四、注意
1、在一切可能抛出异常的地方,请用catch捕获异常。若不捕获,那么报错时,会导致nodejs直接中断!
标签:body,NodeJS,res,数据库,req,let,sql,app,MSSQL From: https://www.cnblogs.com/ricardox3/p/16889824.html