SQL数据安全与权限管理是数据库运维中最重要的环节之一,合理的安全策略和完善的权限配置能够有效避免数据泄露、越权操作等风险,保障企业核心数据资产的安全。
SQL权限管理的基础概念
SQL数据库的权限体系通常是分层级的,不同层级的权限对应不同的操作范围,常见的权限层级包括全局权限、数据库权限、表权限和列权限。
- 全局权限:作用于整个数据库实例,比如创建用户、关闭数据库实例等权限,通常只分配给数据库管理员。
- 数据库权限:作用于单个数据库,比如创建表、删除表、查询所有表数据等权限。
- 表权限:作用于单个数据表,比如对表的增删改查、修改表结构等权限。
- 列权限:作用于表的单个列,比如只允许查询用户表的姓名列,不允许查询手机号、身份证号等敏感列。
用户与角色的管理方法
直接给单个用户分配权限会导致权限管理混乱,维护成本高,更推荐的方式是先创建角色,给角色分配对应的权限,再把角色赋予给对应的用户。
创建用户示例
以MySQL为例,创建用户的语法如下:
-- 创建用户,设置密码,允许从指定IP登录 CREATE USER 'app_reader'@'192.168.0.1' IDENTIFIED BY 'StrongPassword123'; -- 如果需要允许所有IP登录,可以把IP换成% CREATE USER 'app_writer'@'%' IDENTIFIED BY 'StrongPassword456';
角色创建与权限分配
MySQL 8.0及以上版本支持角色功能,创建角色并分配权限的示例如下:
-- 创建只读角色 CREATE ROLE 'read_role'; -- 给只读角色分配查询权限,作用于test_db数据库的所有表 GRANT SELECT ON test_db.* TO 'read_role'; -- 创建读写角色 CREATE ROLE 'write_role'; -- 给读写角色分配增删改查权限 GRANT SELECT, INSERT, UPDATE, DELETE ON test_db.* TO 'write_role'; -- 把角色赋予给用户 GRANT 'read_role' TO 'app_reader'@'192.168.0.1'; GRANT 'write_role' TO 'app_writer'@'%'; -- 设置用户默认激活角色 SET DEFAULT ROLE 'read_role' TO 'app_reader'@'192.168.0.1';
敏感数据的安全防护策略
除了权限控制,还需要针对敏感数据做额外的防护,避免权限被绕过或者数据被非法获取。
数据加密存储
对于手机号、身份证号、银行卡号等敏感字段,建议存储加密后的内容,查询时再解密,避免数据库文件被窃取后直接泄露敏感信息。以下是简单的加密存储示例:
import pymysql
from cryptography.fernet import Fernet
# 生成加密密钥,实际使用中需要妥善保管密钥
key = Fernet.generate_key()
cipher = Fernet(key)
def insert_user(phone):
# 加密手机号
encrypted_phone = cipher.encrypt(phone.encode())
conn = pymysql.connect(host='127.0.0.1', user='app_writer', password='StrongPassword456', database='test_db')
cursor = conn.cursor()
# 插入加密后的手机号
sql = "INSERT INTO user (phone) VALUES (%s)"
cursor.execute(sql, (encrypted_phone,))
conn.commit()
conn.close()
def query_user():
conn = pymysql.connect(host='127.0.0.1', user='app_reader', password='StrongPassword123', database='test_db')
cursor = conn.cursor()
cursor.execute("SELECT phone FROM user")
result = cursor.fetchone()
# 解密手机号
decrypted_phone = cipher.decrypt(result[0]).decode()
print(decrypted_phone)
conn.close()
敏感操作的审计
开启数据库的操作审计功能,记录所有用户的登录行为、权限变更操作、敏感表的增删改查操作,方便出现问题时溯源。MySQL开启通用日志和慢查询日志的配置示例如下:
-- 查看通用日志状态 SHOW VARIABLES LIKE 'general_log%'; -- 开启通用日志,记录所有SQL操作 SET GLOBAL general_log = 'ON'; -- 设置通用日志文件路径 SET GLOBAL general_log_file = '/var/log/mysql/general.log'; -- 查看慢查询日志状态 SHOW VARIABLES LIKE 'slow_query_log%'; -- 开启慢查询日志,记录执行时间超过1秒的SQL SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 1; SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
常见安全风险与规避方法
| 风险类型 | 风险描述 | 规避方法 |
|---|---|---|
| 权限过度分配 | 给普通用户分配了管理员权限,或者给应用用户分配了不必要的写权限 | 遵循最小权限原则,只给用户分配完成工作必需的最小权限,定期审计用户权限 |
| 弱密码问题 | 数据库用户密码过于简单,容易被暴力破解 | 强制密码复杂度要求,定期更换密码,禁止使用默认密码 |
| SQL注入攻击 | 应用端未做参数校验,攻击者通过构造恶意SQL获取或者篡改数据 | 应用端使用参数化查询,不要拼接SQL字符串,对用户输入做严格校验 |
| 未授权访问 | 数据库端口直接暴露在公网,没有做访问IP限制 | 限制数据库只允许内网IP访问,公网访问需要通过跳板机或者VPN,配置防火墙规则 |
权限定期审计流程
建议每季度做一次权限审计,流程如下:
- 导出所有数据库用户和对应的权限列表,检查是否存在权限过大的用户。
- 检查长期未登录的僵尸用户,及时禁用或者删除。
- 检查角色权限是否符合当前业务需求,移除不再需要的权限。
- 检查审计日志,确认是否存在异常的权限变更或者敏感操作。
做好SQL数据安全与权限管理需要结合权限分级、角色管理、数据加密、操作审计等多个措施,形成完整的安全防护体系,才能最大程度降低数据安全风险。