问题
How do I insert a value into a select statement using JavaScript, specifically when using express and postgres?
The createUser, and listAllUsers, is working (included below for reference). The try/catch is working and satisfying the request or throwing the error for those two as well.
Any help would be greatly appreciated!
When using Postman, the output that I receive when I send the get (localhost:4000/user/id with a x-www-formurlencoded key value user_id = 3) is…
{
"name": "error",
"length": 90,
"severity": "ERROR",
"code": "42601",
"position": "37",
"file": "scan.l",
"line": "1134",
"routine": "scanner_yyerror"
}
And in the terminal, it shows the following (trapped from my console.log).
3
QUERY: SELECT * FROM users WHERE user_id = ${user_id}
When I user curl it says the same in the terminal. Here is the curl command and putput…
curl -X GET localhost:4000/user/3
{"name":"error","length":90,"severity":"ERROR","code":"42601","position":"37","file":"scan.l","line":"1134","routine":"scanner_yyerror"}ww10sc2353621:~ james.mcgreggor$ curl -X GET localhost:4000/user/3
Ultimately the 3 that I am passing as the user_id is not being substituted in the select statement. That is my problem. I cannot figure out how to correctly do this. Should I even be taking this approach, or should I try passing it as a parameter in the URL?
This is from my User class file (User.js)
const db = require('../connectors/db.js');
class User {
constructor(id, user_id, first_name, middle_initial, last_name, email, type) {
this.id = id;
this.first_name = first_name;
this.middle_initial = middle_initial;
this.last_name = last_name;
this.email = email;
this.type = type;
this.user_id = user_id;
}
static newUser(user_id, first_name, middle_initial, last_name, email, type) {
return db.one(`
INSERT INTO users ("user_id", "first_name", "middle_initial", "last_name", "email", "type")
VALUES ('${user_id}', '${first_name}', '${middle_initial}', '${last_name}', '${email}', '${type}')
returning id
`)
}
static async allUsers() {
const findAllQuery = 'SELECT * FROM users;';
return db.query(findAllQuery)
}
static async selectUser(user_id) {
console.log(user_id);
const findOneQuery = 'SELECT * FROM users WHERE user_id = ${user_id}';
return db.query(findOneQuery)
}
}
module.exports = User;
This is from my Routes file (Routes.js)
const express = require('express');
const dataFunctions = require('./catalog.js');
const AppRouter = express.Router();
AppRouter.post('/user', dataFunctions.createUser);
AppRouter.get('/users', dataFunctions.listAllUsers);
AppRouter.get('/user/:id', dataFunctions.listUserByUserID);
AppRouter.delete('/user/:id', dataFunctions.deleteUserByUserID);
module.exports = AppRouter;
This is from my Catalog file (Routes.js)
const Users = require('../models/users.js')
// Create
async function createUser(req, res) {
try {
console.log(req.body);
const userId = await Users.newUser(req.body.user_id, req.body.first_name, req.body.middle_initial, req.body.last_name, req.body.email, req.body.type)
res.status(201).send(`User ID: ${userId.id}`);
} catch(error) {
res.status(400).send(error);
}
}
// List all
async function listAllUsers(req, res) {
try {
const userList = await Users.allUsers();
console.log(userList);
res.status(200).send(userList);
} catch(error) {
res.status(400).send(error);
}
}
// List by ID
async function listUserByUserID(req, res) {
try {
const userList = await Users.selectUser(req.body.user_id);
console.log(userList);
res.status(200).send(userList);
} catch(error) {
res.status(400).send(error);
}
}
module.exports = {
createUser,
listAllUsers,
listUserByUserID
}
回答1:
Instead of using single quotes in select query in static async selectUser use ``.
回答2:
Never use string concatenation for querying, you already have mechanism called prepared statement, signature like
.query('SELECT * FROM `books` WHERE `author` = ?', ['David'])
It will sanitize input for you and partially prevent sql-injection attacks, also always do validation of input values. And if you are not want to use ORM like typeorm
, Sequelize
, you can use knex.js
which can only create query strings and fully manage db interaction
回答3:
You should never insert the values directly into your query like that. Consider the example:
db.query(`
INSERT INTO messages (message, username)
VALUES ('${message}', '${username}')
`);
If the username
was my authenticated username, but the message
was whatever value I typed into the UI, I could pretend to be someone else by sending a message like: I am stupid', 'someone_else') --
The SQL would then look like:
INSERT INTO messages (message, username)
VALUES ('I am stupid', 'someone_else') --', 'my_username')
The --', 'my_username')
bit is treated as a comment, so it looks like someone_else
said I am stupid
. This is one of the most common and easily exploitable vulnerabilities in web applications.
Solution 1
You could parameterise your query:
db.query(`
INSERT INTO messages (message, username)
VALUES (?, ?)
`, [message, username]);
This is secure, but harder to read (in my opinion) and you have to be very careful to always do this consistently.
Solution 2
https://www.atdatabases.org provides database APIs that are relatively easy to use, and totally safe from this kind of attack. You would just do:
import connect, {sql} from '@databases/pg';
const db = connect();
db.query(sql`
INSERT INTO messages (message, username)
VALUES (${message}, ${username})
`);
to safely execute the same query. The sql
tag ensures the data is properly handled/escaped and @databases/pg
automatically enforces that you always add the sql
tag. N.B. there are then no quotes around the parameters.
来源:https://stackoverflow.com/questions/56895856/how-do-i-insert-a-value-into-a-select-statement-using-javascript-specifically-w