在构建应用的数据访问层时,很多开发者习惯用SELECT *快速取数,但这会把表里诸如password、token、salt等系统敏感字段一并查出,带来严重安全隐患。通过调整SELECT列表,只选取业务真正需要的列,是从SQL查询中剔除敏感字段最直接有效的做法。

为什么不能用SELECT *
使用星号会返回表中全部列,当表结构后续加入内部字段时,这些字段也会自动暴露给调用方。此外,SELECT * 不利于索引覆盖和查询优化。应当显式写出需要的列名,从源头排除敏感信息。
基本写法:明确列名
假设用户表users包含id、name、email、password、token五个字段,其中password和token属于系统敏感字段,正确写法如下:
-- 只查询非敏感的业务字段 SELECT id, name, email FROM users WHERE id = 1001;
使用视图封装安全列表
如果多个业务模块都要查用户公开信息,可以建立视图,把剔除敏感字段的查询固化下来:
CREATE VIEW v_user_public AS SELECT id, name, email FROM users; -- 业务层直接查视图,无需关心敏感列 SELECT id, name, email FROM v_user_public;
动态拼接查询的注意点
在代码里动态生成SQL时,应使用白名单控制列名,不要拼接外部传入的字段:
# 允许的业务字段白名单 allowed_cols = ['id', 'name', 'email'] # 外部请求希望获取的字段 requested = ['id', 'password'] # 过滤掉敏感或非法字段 safe_cols = [c for c in requested if c in allowed_cols] sql = 'SELECT ' + ', '.join(safe_cols) + ' FROM users' print(sql)
权限层面的辅助手段
除调整SELECT列表外,还可通过数据库权限回收敏感列的访问权,或只授权视图而非基表,形成双重保护。总之,从查询语句本身剔除系统敏感字段,是成本最低且最可控的防护方式。