永远不要相信前端传来的数据,对于资深开发者而言,这几乎是一种本能,无需过多解释。然而,初入职场的开发新手可能会感到困惑:为何要对前端传来的数据持有如此不信任的态度?难道人与人之间连基本的信任都不存在了吗?
API恶意调用
这种“恶意调用”是实现 SQL 注入攻击的一种常见途径,它展示了攻击者如何通过 URL 参数发起攻击。
再来看一个例子,假设有一个用户信息查询接口,前端会发送一个用户 ID 到后端,后端根据用户 ID 查询用户信息并返回。后端代码如下(未采用防御式编程):
from flask import Flask, request, jsonify i
mport sqlite3 app = Flask(__name__) @app.route('/user', methods=['GET'])
def get_user(): user_id = request.args.get('id') conn = sqlite3.connect('example.db') cursor = conn.cursor() query = f"SELECT * FROM users WHERE id={user_id}" cursor.execute(query) result = cursor.fetchone() conn.close() if result: return jsonify(result) else: return jsonify({"error": "User not found"}), 404
if __name__ == '__main__': app.run(debug=True)
在这个例子中,后端代码直接将用户输入的 user_id 拼接到 SQL 查询语句中,没有进行任何校验或处理。这使得该接口容易受到 SQL 注入攻击。
恶意调用示例:假设攻击者通过浏览器或其他工具向该接口发送以下请求:
GET /user?id=1 OR 1=1
生成的 SQL 查询语句将是:
SELECT * FROM users WHERE id=1 OR 1=1
由于 1=1 永远为真,这条查询语句会返回所有用户的信息,而不是只返回 ID 为 1 的用户信息。攻击者可以利用这种方式获取数据库中所有用户的信息,造成严重的安全问题。
由此可见,前端传来的数据并非绝对可靠。对于后端来说,这些数据就像未经筛选的原材料,其中可能夹杂着各种风险。因此,后端必须对前端传来的数据进行二次校验,这正是防御式编程的核心思想。