簡體   English   中英

如何防止 Flask-SQLAlchemy 中的 SQL 注入? 有沒有更好的方法從 CSV 加載數據?

[英]How do I prevent SQL injections in Flask-SQLAlchemy? Is there a better way to load data from CSV?

我正在嘗試使用 Flask、SQLAlchemy 和 PostgreSQL/psycopg2 將來自 Internet 的數據快速加載到表中。 我和一位同事發生了輕微的爭吵。 我們稱他為“爸爸”。 爸爸爭辯說我們不能執行原始的 SQL 查詢,因為 SQL 注入的可能性。 我認為我們可以,如果它可能被格式化,這很難做到,通常應該使用 ORM。 在我看來,以下示例似乎是一個足夠簡單的問題。

# Flask-SQLAlachemy
from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy

server = Flask(__name__)
server.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
server.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql+psycopg2://...'
db = SQLAlchemy(server)

@server.route('/<column>')
def index(column):
    result = db.session.execute("SELECT" + column + "from item_profit")
    return render_template('index.html', data=result)

基本上有人可以將任何原始 SQL 插入列並返回該表。 有關其他簡單注射的信息,請參見此鏈接 我看到了這個 SO 答案(見第二個答案),這似乎暗示格式正確的字符串不會導致 SQL 注入。 他們的代碼如下所示:

result = db.session.execute('SELECT * FROM my_table WHERE my_column = :val', {'val': 5})

爸爸說,不少公司的 DBA 阻止其他部門擁有執行權限,即他們無法使用

    result = db.session.execute("...")

我認為這是因為他們擔心普通用戶不知道正確格式化它。 那是對的嗎? 並不是執行 SQL 查詢會導致 SQL 注入,而是格式不正確的執行查詢會導致注入。 這就是人們說使用 ORM 的原因,因為它始終確保格式正確的查詢。 這是正確的想法嗎? ORM 系統只是在幕后執行。 如果執行查詢是一個注入問題,那么即使是 ORM 也無法使用。 哎呀,即使是 SQL 也無法使用,對嗎? 我希望在某些情況下使用原始 SQL,因為我們可能正在處理巨大的數據集,其中處理速度是一個主要因素,而 ORM 要慢得多。

然后我的后續問題是,將 CSV 加載到 SQL 數據庫中同時最小化原始 SQL 的最佳方法是什么? 爸爸使用 PgAdmin 導入將 CSV 導入到 postgres 中(節省了大量在 psql 中寫出導入的時間)。 I know another way would be to use pandas pandas.Dataframe.to_sql() method, but I do not see bringing pandas in for this seems like the best design here. 我通常使用 ORM,但我不確定是否有一種快速獲取 CSV 的方法。 假設我有一個表Product的 csv ,它有兩列NameCost 為了在 ORM 中實現這一點,我將執行以下操作:

...

db = SQLAlchemy(app)

class Product(db.Model):
    __tablename__ = 'product'

    name = db.Column(db.String)
    cost = db.Column(db.Double)

但是,我又回到了將 CSV 放入 python 以加載到表中的問題。 有來自_csv('')的pandas。 我想我也可以打開文件本身並循環遍歷它。 就像是

for record in csv_file:
    product = Product(name=..., cost=...)
    db.session.add(product)
    db.session.commit()

有沒有更好的辦法? ORM 是否有辦法加載 CSV,同時允許我在大多數時間避免原始 SQL?

這是很多問題。

@server.route('/<column>')
def index(column):
    result = db.session.execute("SELECT" + column + "from item_profit")
    return render_template('index.html', data=result)

如果您限制列變量可以包含的內容,這看起來很簡單。 但問題是你永遠不知道代碼將來會發生什么。 所有可能的檢查都可以 go 離開,只有這個“SELECT”+列+“來自...”會保留,然后可能會出現問題。 這就是為什么我總是反對構建 sql 並將其發送到數據庫中。

爸爸說,不少公司的 DBA 阻止其他部門擁有執行權限,即他們無法使用

我不確定這到底是什么意思。 某些公司或某些應用程序可能會阻止數據庫運行存儲過程以外的任何其他內容。 因此數據庫不能被濫用,權限更容易檢查。 但是數據庫無法阻止 sqlalchemy 執行 db.session.execute。 db.session.execute can execute select, update, delete, stored procedure, any sql in general, and RDBMS will apply premissions to that sql. 無論您使用原始 sql,還是您的原始 sql 是由 ORM 或任何其他構建器構建的,都沒有關系。

現在,即使是 SQLAlchemy 也有 2-3 個級別。 ORM 是最高級別。 然后是 QL(查詢語言),它允許您構建和執行 SQL。 最后,您可以執行文字 SQL。

在字面量 SQL 中可以使用參數,例如: https://docs.sqlalchemy.org/en/13/core/tutorial.html#specifying-bound

在 QL 中,您可以輕松構建如下查詢:

q = table_name.insert({
    "id": 3321, "name": python_var_name, "age": python_var_age,
})
conn.execute(q)
# or even session.execute(q)  but consult the docs

在 ORM 中,您已經知道該怎么做。 但是當您要插入大量記錄時,您可能正在考慮使用 bulk_insert_mapping、 https://stackoverflow.com/a/35495327/3939992但它將使用所有 ORM 機制,您可能不想要。

使用 QL 會更好。 Read the tutorial, it is all in there: https://docs.sqlalchemy.org/en/13/core/tutorial.html https://docs.sqlalchemy.org/en/13/core/tutorial.html#executing -多重陳述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM