首页 > 解决方案 > 带有 SQL Server 用户身份验证的 NodeJs 登录表单

问题描述

我在使用 SQL Server 数据库对用户进行身份验证时遇到问题。我已经建立了与数据库的连接,并且可以从数据库中提取用户。但是,当尝试查询数据库进行身份验证时,我收到“未处理的承诺 - 连接已关闭”错误。

app.js 文件:

var sql = require("mssql");
var express = require("express");
var session = require("express-session");
var bodyParser = require("body-parser");
var path = require("path");


var dbconfig = {
  server: "Server",
  database: "Test",
  user: "########",
  password: "####################",
  port: 1433,
  options : {
    encrypt: false
  }
};

var app = express();
app.use(session({
  secret: 'Secret',
  resave: true,
  saveUninitalized: true

}));

app.use(bodyParser.urlencoded({
  extended: true
}));
app.use(bodyParser.json());

app.get('/', function(request, response) {
  response.sendFile(path.join(__dirname + '/login.html'));
});

app.post('/auth', function(request, response) {
      var username = request.body.username;
      var password = request.body.password;
      var conn = new sql.ConnectionPool(dbconfig);
      var req = new sql.Request(conn);
      if (username && password) {
        conn.connect();
        req.query('Select * from Admin where username = ? and password = ?', [username, password], function(error, results, fields) {
            if (results.length > 0) {
              request.session.loggedin = true;
              resquest.session.username = username;
              response.redirect('/home');
            } else {
              response.send('Username and/or Password not found');
            }
            conn.close();
            response.end();
          });

        } else{
          response.send('Please enter Username and Password');
        }

      });

      app.get('/home', function(request, response){
        if(request.session.loggedin){
          response.send('Welcome back,' + request.session.username + '!');

        }else{
          response.send('Please sign');
        }
        response.end();
      });
      app.listen(3000);
      function getEMP() {
        var conn = new sql.ConnectionPool(dbconfig);
        var req = new sql.Request(conn);

        conn.connect(function(err) {
          if (err) {
            console.log(err);
            return;
          }
          req.query("Select * from Admin", function(err, recordset) {
            if (err) {
              console.log(err)
            } else {
              console.log(recordset)
            }
            conn.close();
          });
        });
      }

      getEMP();

getEMP函数按预期返回数据库中的所有管理员。这就是为什么我肯定连接正在工作的原因。此功能用于测试连接。

错误

UnhandledPromiseRejectionWarning:ConnectionError:连接已关闭。
在 Request._query (///nodeconSQL/node_modules/mssql/lib/base/request.js:447:37)
在 Request._query (///nodeconSQL/node_modules/mssql/lib/tedious/request.js:346: 11)
在 shared.Promise (///nodeconSQL/node_modules/mssql/lib/base/request.js:413:12)
在新的 Promise ()
在 Request.query (///nodeconSQL/node_modules/mssql/lib/base /request.js:412:12)
在 /home/devops-01/nodeconSQL/app.js:43:13
在 Layer.handle [as handle_request] (///nodeconSQL/node_modules/express/lib/router/layer. js:95:5)
在下一个 (///nodeconSQL/node_modules/express/lib/router/route.js:137:13)
在 Route.dispatch (///nodeconSQL/node_modules/express/lib/router/route. js:112:3)
在 Layer.handle [as handle_request] (///nodeconSQL/node_modules/express/lib/router/layer.js:95:5)

标签: node.jssql-server

解决方案


您的函数getEMP()使用回调conn.connect(),以便在尝试执行查询之前等到建立连接。

尝试登录的函数在尝试打开连接后立即执行查询,但是由于建立连接需要一些时间,这就是为什么您会收到连接未打开的错误。

将您的登录查询放在conn.connect(function(err){ /* login code */ })构造中,就像在您的getEMP()函数中一样。然后,您需要确保您可以访问回调函数中的请求和响应对象,例如通过在回调函数上使用.bind()将请求和响应对象放入this对象中。另一种选择是使用闭包函数来获取回调数据。

使用闭包的示例:

app.post('/auth', function(request, response) {
    var username = request.body.username;
    var password = request.body.password;

    if (username && password) {
        var conn = new sql.ConnectionPool(dbconfig);
        conn.connect((function(){
            var thisConn = conn;
            var req = new sql.Request(thisConn);

            return function(){ //connect callback
            req.query('Select * from Admin where username = ? and password = ?', [username, password], 
            (function(){
                var req = request;
                var resp = response;
                var conn = thisConn;

                return function(error, results, fields) { // query callback
                    if (results.length > 0) {
                        req.session.loggedin = true;
                        req.session.username = username;
                        resp.redirect('/home');
                    } else {
                        response.send('Username and/or Password not found');
                    }
                    conn.close();
                    resp.end();
                };
            })());
            };
        })());
    } else {
      response.send('Please enter Username and Password');
    }
});

使用绑定的示例:

...

// Inside your /auth route
// make an object with the data our callback needs, to use with .bind()
var callbackData = {"conn": conn, "request": request, "response": response};
var connectCallback = function(err){
    if (err) {
        console.log(err);
        return;
     }
    req.query('Select * from Admin where username = ? and password = ?',
        [username, password], function(error, results, fields) {
        // 2nd level of callback, query callback
        if (results.length > 0) {
              this.request.session.loggedin = true;
              this.resquest.session.username = username;
              this.response.redirect('/home');
        } else {
              this.response.send('Username and/or Password not found');
        }
        this.conn.close();
        this.response.end();
    }.bind(this)); // pass our 'this' object through to the next level
}.bind(callbackData);

conn.connect(connectCallback);
...

推荐阅读