Resolve Expression from Node API Endpoint (Boolean

2019-08-05 22:55发布

问题:

I am trying to validate an API key to run an API endpoint function.

server.js

let db = require("./sql/rest_functions")            // Custom modules
let session = require("./sql/session_management")

app.get("/node/api/mssql/test", function(req, res) {
   if(session.validateKey(req)) {
     db.mssqlQuery(req, res)
   }
 })

session.js

exports.validateKey = function(req) {
  return sql.connect(config.properties)
    .then(pool => {
      return pool.request()
        .query("SELECT CASE WHEN EXISTS (SELECT * FROM Login WHERE (username = '" + req.header("username") + "' AND apiKey = '" + req.header("apiKey") + "')) THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT) END")
        .then(response => {
          console.log(typeof response[0]['']) // returns boolean
          return response[0]['']              // return nested value to get true / false response
        })
    })
}

The validateKey function is returning true and false (I think as plain text), and I would like it to resolve to a boolean that can be passed into the API test function.

I have tried this JSON.parse method and the session.validateKey(req) == 'true' design pattern, but neither case resolves to an expected behavior.

How can I resolve the returned value to verify the user's credentials?

回答1:

I would suggest simply returning the count of rows from the database and validating that there exists 1 entry (or more than one, depending on how your data are structured).

Note that to mitigate against SQL Injection, you must use parameter binding, illustrated below; the library does not "automatically" protect against injection, as per the documentation if you do not use parameter binding. Change VarChar(100) to whatever the column type is for those fields.

exports.validateKey = async function(req) {
  return await sql.connect(config.properties)
    .then(pool => pool.request()
        .input('user', sql.VarChar(100), req.header("username"))
        .input('key', sql.VarChar(100), req.header("apiKey"))
        .query('SELECT COUNT(*) AS valid FROM Login WHERE username = @user AND apiKey = @key')
        .then(response => result.recordset[0].valid === 1)
    )
}

Note that validateKey will return a Boolean Promise, so we've added async/await to save modifying the route controller.

Note that I've removed the braces from most of the fat arrow functions: they're all one statement so they're redundant.

Caveat: I can't actually try this, it's an educated guess from reading the documentation. I hope it helps.