PostgreSQL, python, asyncpg. Как избежать SQL инъекций?

Рейтинг: 0Ответов: 1Опубликовано: 13.05.2023

Пишу чат-ботов для telegram на языке python с использованием библиотеки aiogram. До сегодняшнего дня использовал базу данных SQLite3, но возникла необходимость использовать что-то более "мощное". В процессе того как я пытался использовать PostgreSQL, столкнулся с, наверное, различием в синтаксисе. Когда я использую Sqlite3, чтобы избежать SQL инъекции я использую следующий код:

with sq.connect(db_path) as con:
    cur = con.cursor()
    
    cur.execute('''
        insert into users(t_id) values(?)
    ''', (123123123,))
    
    result = cur.execute('''
        select * from users where t_id = ? and id = ?
    ''', (123123123, 1))

Но с PostgreSQL такое не прокатывает

Я немного покопался в интернете и сделал примерно следующее. файл db.py и main.py.

Файл db.py

import asyncpg


class DB:
    def __init__(self, user, password, database, host):
        self.user = user
        self.password = password
        self.database = database
        self.host = host
        self.connection = None

    async def connect(self):
        self.connection = await asyncpg.connect(user=self.user, password=self.password, database=self.database, host=self.host)

    async def execute(self, query, *args):
        if self.connection is None:
            await self.connect()
        result = await self.connection.fetch(query, *args)
        return result

    async def close(self):
        if self.connection is not None:
            await self.connection.close()

Файл main.py

import asyncio
from aiogram import Bot, types
from aiogram.dispatcher import Dispatcher
from aiogram.utils import executor
from db import DB

db = DB(user='юзер', password='пароль', database='база', host='localhost')
bot = Bot(token='токен')
dp = Dispatcher(bot)


async def on_startup(dispatcher):
    await db.execute('''
        create table if not exists users(
            id integer primary key,
            t_id integer
        )
    ''')


@dp.message_handler(content_types=types.ContentType.ANY, state='*')
async def message_handler(message: types.Message):
    result = await db.execute(f'''
        select id from users where t_id = ?
    ''', (message.from_user.id,))
    if not len(result):
        result = await db.execute('''
            insert into users(t_id) values(?)
        ''', (message.from_user.id,))


# Запускаем бота
if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(db.connect())
    executor.start_polling(dp, loop=loop, on_startup=on_startup, skip_updates=True)

Два вопроса: как я могу избежать SQL инъекций в PosgreSQL? и правильно ли я использую классы для управление базой данных? Любая критика приветствуется

Ответы

▲ 1

Не могу сказать по поводу использования классов, но знаю, как избежать SQL инъекций в PosgreSQL. Покажу на примере:

    cur.execute("""
    INSERT INTO client (first_name, last_name, email) VALUES (%s, %s, %s) RETURNING client_id;
    """, (first_name, last_name, email))

Удачи!