Prepared Statements
Prepared Statements ์ง์ญํ๋ฉด โ์ฌ์ ์ ์ธโ์ผ๋ก ๋ ๋๋ถ๋ถ์ ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์คํ
์์ ์ฌ์ฉ ๊ฐ๋ฅํ ๋ฐฉ์์ผ๋ก, SQL Injection์ ๋ฐฉ์งํ๊ธฐ ์ํด ๋งค๊ฐ๋ณ์ํ๋ ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ฟผ๋ฆฌ ๋ฌธ์์ด๊ณผ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฆฌํ๋ ๋ฐฉ์์ด๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก ์ธ์ ํ์๊ณผ ๊ธธ์ด์ ๋ํด ๊ฒ์ฆ์ ํ๊ณ , ์๋ ๋งํฌ์ ๊ฐ์ด SQL Escape ํจ์๋ฅผ ์ฌ์ฉํ๋ ๋ฑ์ ๋ฐฉ์์ผ๋ก ๋ง์ ์๋ ์์ง๋ง SQL Injection์ ๊ณต๊ฒฉํ๋ ๋ฐฉ์์ ๋ฌด์ฒ์ด๋ ๋ค์ํ๊ธฐ ๋๋ฌธ์ SQL ๊ตฌ์กฐ์ ์ผ๋ก ์๋ฐฉํ๋ ๊ฒ์ด ๊ฐ์ฅ ์ข๋ค.
Statements vs Prepared Statements
๊ธฐ์กด ๋ฐฉ์ (Dynamic SQL Statements):
โข
ํด๋ผ์ด์ธํธ๋ SQL ์ฟผ๋ฆฌ ๋ฌธ์์ด์ ๋ง๋ ๋ค. ์ด๋ ์ฌ์ฉ์ ์
๋ ฅ์ด ์ง์ ์ฟผ๋ฆฌ ๋ฌธ์์ด์ ํฌํจ๋๋ค.
โข
์์ฑ๋ ์ฟผ๋ฆฌ ๋ฌธ์์ด์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค ์๋ฒ๋ก ์ ์ก๋๋ค.
โข
๋ฐ์ดํฐ๋ฒ ์ด์ค ์๋ฒ์์ ์ฟผ๋ฆฌ ๋ฌธ์์ด์ ํ์ฑ, ์ต์ ํ, ์ปดํ์ผํ ํ ์คํํ๋ค.
์ด ๊ณผ์ ์์ ์ฌ์ฉ์ ์
๋ ฅ์ด ์ฟผ๋ฆฌ ๋ฌธ์์ด์ ์ง์ ํฌํจ๋๊ธฐ ๋๋ฌธ์ ๊ณต๊ฒฉ์๊ฐ SQL ๊ตฌ๋ฌธ์ ์กฐ์ํด SQL Injection์ ์ํํ๊ฒ ๋๋ค.
Prepared Statements ๋ฐฉ์:
โข
ํด๋ผ์ด์ธํธ๋ ๋ ๋ถ๋ถ(์ฟผ๋ฆฌ ํ
ํ๋ฆฟ๊ณผ ๋ณ์ ๊ฐ)์ผ๋ก ๋๋์ด์ง ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ๋ค.
โข
์ฟผ๋ฆฌ ํ
ํ๋ฆฟ์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค ์๋ฒ๋ก ์ ์ก๋๋ค.
โข
๋ฐ์ดํฐ๋ฒ ์ด์ค ์๋ฒ์์ ์ฟผ๋ฆฌ ํ
ํ๋ฆฟ์ ํ์ฑ, ์ต์ ํ, ์ปดํ์ผํ๊ณ , ์คํ ๊ณํ์ ์ ์ฅํด ๋๋๋ค.
โข
ํด๋ผ์ด์ธํธ๋ ๋ณ์ ๊ฐ(์ฌ์ฉ์ ์
๋ ฅ)์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์๋ฒ๋ก ์ ์กํ๋ค.
โข
๋ฐ์ดํฐ๋ฒ ์ด์ค ์๋ฒ์์ ์ ์ฅ๋ ์คํ ๊ณํ์ ๋ณ์ ๊ฐ์ ๋ฐ์ธ๋ฉํ ํ, ์ฟผ๋ฆฌ๋ฅผ ์คํํ๋ค.
Prepared Statements ๋ฐฉ์์์๋ ์ฟผ๋ฆฌ ํ
ํ๋ฆฟ๊ณผ ๋ณ์ ๊ฐ์ด ๋ถ๋ฆฌ๋์ด ์ ์ก๋๋ฏ๋ก, ์ฌ์ฉ์ ์
๋ ฅ์ด SQL ๊ตฌ๋ฌธ์ ์ง์ ํฌํจ๋์ง ์์ SQL ๋ฌธ๋ฒ์ผ๋ก ์ฒ๋ฆฌ๋์ง ์๊ธฐ์ SQL Injection์ ํจ๊ณผ์ ์ผ๋ก ๋ฐฉ์งํ ์ ์๋ค.
DB๋ณ ์ฌ์ฉ ๋ฐฉ๋ฒ
์๋ฅผ ๋ค๋ฉด SQL๋ฌธ ์์ ? (๋ฌผ์ํ)๋ฅผ ์ฌ์ฉํ์ฌ ์ด ๋ฌผ์ํ์ ์ธ์๋ฅผ ๋งค์นญ์ํค๋ Placeholder ๋ฐฉ์์ ํตํด ๋ฐ์ธ๋ฉ ๋ณ์๋ฅผ ๋๊ฒจ์ฃผ๋ ๊ตฌ์กฐ๋ก ์ด๋ฃจ์ด์ง๋ค.
๊ฐ๋จํ ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
1.
PHP
$stmt = $pdo->prepare('SELECT * FROM users WHERE username = ? AND password = ?');
$stmt->execute([$username, $password]);
PHP
๋ณต์ฌ
2.
Python
cursor.execute('SELECT * FROM users WHERE username = %s AND password = %s', (username, password))
Python
๋ณต์ฌ
3.
Java
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM users WHERE username = ? AND password = ?");
pstmt.setString(1, username);
pstmt.setString(2, password);
ResultSet rs = pstmt.executeQuery();
Java
๋ณต์ฌ
4.
Ruby
stmt = conn.prepare('SELECT * FROM users WHERE username = ? AND password = ?')
stmt.execute(username, password)
Ruby
๋ณต์ฌ
5.
Node.js
db.query('SELECT * FROM users WHERE username = ? AND password = ?', [username, password], (err, result) => {
// handle result or error
});
JavaScript
๋ณต์ฌ
์ด๋ฅผ ๋ค์ 4๊ฐ DB์ ๋ํด Python, JS, PHP ๋ฐฉ์์ ๋ํด ์ ๋ฆฌํ๋ค.
๋๋ถ๋ถ import ๋ฐฉ์๋ง ๋ค๋ฅผ ๋ฟ ๊ฑฐ์ ๋์ผํ ํํ๋ฅผ ๋๋ค.
โข
MySQL
โข
postgresql
โข
oracle
โข
mariadb
1. MySQL
python
import MySQLdb
conn = MySQLdb.connect(host=host, user=user, passwd=passwd, db=db)
cursor = conn.cursor()
query = "SELECT * FROM mytable WHERE column1 = %s AND column2 = %s"
params = ("value1", "value2")
cursor.execute(query, params)
result = cursor.fetchall()
Python
๋ณต์ฌ
javascript(node.js)
const mysql = require('mysql');
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'mydb'
});
const query = 'SELECT * FROM mytable WHERE column1 = ? AND column2 = ?';
const values = ['value1', 'value2'];
connection.query(query, values, function (error, results, fields) {
if (error) throw error;
console.log('The result is: ', results);
});
JavaScript
๋ณต์ฌ
PHP
PHP์์ MySQL Prepared Statements๋ฅผ ์์ฑํ๊ธฐ ์ํด์๋ mysqli๋๋ PDOํด๋์ค๋ฅผ ์ฌ์ฉํ๋ค
๋์ฒด๋ก PDO ํด๋์ค๊ฐ ๋๋ถ๋ถ์ DB์์ ์ฌ์ฉ๋๊ธฐ ๋๋ฌธ์ PDO๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข๋ค.
mysqli
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";
// Create connection
$conn = mysqli_connect($servername, $username, $password, $dbname);
// Prepare statement
$stmt = mysqli_prepare($conn, "SELECT * FROM mytable WHERE column1 = ? AND column2 = ?");
// Bind parameters
mysqli_stmt_bind_param($stmt, "ss", $value1, $value2);
// Set parameters and execute
$value1 = "value1";
$value2 = "value2";
mysqli_stmt_execute($stmt);
// Fetch results
$result = mysqli_stmt_get_result($stmt);
$data = mysqli_fetch_all($result, MYSQLI_ASSOC);
PHP
๋ณต์ฌ
PDO (PHP Data Objects)
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";
// Create connection
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// Prepare statement
$stmt = $conn->prepare("SELECT * FROM mytable WHERE column1 = :value1 AND column2 = :value2");
// Bind parameters
$stmt->bindParam(':value1', $value1);
$stmt->bindParam(':value2', $value2);
// Set parameters and execute
$value1 = 'value1';
$value2 = 'value2';
$stmt->execute();
// Fetch results
$result = $stmt->fetchAll();
PHP
๋ณต์ฌ
2. PostgreSQL
python
import psycopg2
conn = psycopg2.connect(host=host, user=user, password=password, dbname=dbname)
cursor = conn.cursor()
query = "SELECT * FROM mytable WHERE column1 = %s AND column2 = %s"
params = ("value1", "value2")
cursor.execute(query, params)
result = cursor.fetchall()
Python
๋ณต์ฌ
javascript(node.js)
const { Pool } = require('pg');
const pool = new Pool({
user: 'username',
host: 'localhost',
database: 'mydb',
password: 'password',
port: 5432
});
const query = {
text: 'SELECT * FROM mytable WHERE column1 = $1 AND column2 = $2',
values: ['value1', 'value2'],
};
pool.query(query, (err, res) => {
if (err) {
console.error(err);
return;
}
console.log(res.rows);
pool.end();
});
JavaScript
๋ณต์ฌ
PHP
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";
// Create connection
$conn = new PDO("pgsql:host=$servername;dbname=$dbname", $username, $password);
// Prepare statement
$stmt = $conn->prepare("SELECT * FROM mytable WHERE column1 = :value1 AND column2 = :value2");
// Bind parameters
$stmt->bindParam(':value1', $value1);
$stmt->bindParam(':value2', $value2);
// Set parameters and execute
$value1 = 'value1';
$value2 = 'value2';
$stmt->execute();
// Fetch results
$result = $stmt->fetchAll();
PHP
๋ณต์ฌ
3. Oracle
python
import cx_Oracle
conn = cx_Oracle.connect(user, password, dsn)
cursor = conn.cursor()
query = "SELECT * FROM mytable WHERE column1 = :value1 AND column2 = :value2"
params = {"value1": "value1", "value2": "value2"}
cursor.execute(query, params)
result = cursor.fetchall()
Python
๋ณต์ฌ
javascript(node.js)
const oracledb = require('oracledb');
async function run() {
let connection;
try {
connection = await oracledb.getConnection({
user: 'hr',
password: 'welcome',
connectString: 'localhost/orcl'
});
const result = await connection.execute(
`SELECT * FROM mytable WHERE column1 = :value1 AND column2 = :value2`,
['value1', 'value2']
);
console.log(result.rows);
} catch (err) {
console.error(err);
} finally {
if (connection) {
try {
await connection.close();
} catch (err) {
console.error(err);
}
}
}
}
run();
JavaScript
๋ณต์ฌ
PHP
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";
// Create connection
$conn = new PDO("oci:host=$servername;dbname=$dbname", $username, $password);
// Prepare statement
$stmt = $conn->prepare("SELECT * FROM mytable WHERE column1 = :value1 AND column2 = :value2");
// Bind parameters
$stmt->bindParam(':value1', $value1);
$stmt->bindParam(':value2', $value2);
// Set parameters and execute
$value1 = "value1";
$value2 = "value2";
$stmt->execute();
// Fetch results
$result = $stmt->fetchAll();
PHP
๋ณต์ฌ
4. MariaDB
python
import mysql.connector
cnx = mysql.connector.connect(
host="localhost",
user="username",
password="password",
database="mydb"
)
cursor = cnx.cursor(prepared=True)
stmt = "SELECT * FROM mytable WHERE column1 = ? AND column2 = ?"
params = ("value1", "value2")
cursor.execute(stmt, params)
result = cursor.fetchall()
for row in result:
print(row)
cursor.close()
cnx.close()
Python
๋ณต์ฌ
javascript(node.js)
const mysql = require('mysql');
const connection = mysql.createConnection({
host: 'localhost',
user: 'username',
password: 'password',
database: 'mydb'
});
const query = 'SELECT * FROM mytable WHERE column1 = ? AND column2 = ?';
const values = ['value1', 'value2'];
connection.query(query, values, function (error, results, fields) {
if (error) throw error;
console.log('The result is: ', results);
});
JavaScript
๋ณต์ฌ
PHP
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";
// Create connection
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// Prepare statement
$stmt = $conn->prepare("SELECT * FROM mytable WHERE column1 = ? AND column2 = ?");
// Bind parameters
$stmt->bindParam(1, $value1);
$stmt->bindParam(2, $value2);
// Set parameters and execute
$value1 = "value1";
$value2 = "value2";
$stmt->execute();
// Fetch results
$result = $stmt->fetchAll();
PHP
๋ณต์ฌ