对于一个系统,特别是开放给互联网用户使用的系统来讲,系统的安全性是重要问题。
一个系统,如果系统架构差一点儿,最多开发效率低;
代码写得差一点儿,最多系统运行速度慢;
但是如果系统安全有问题,导致核心业务数据被泄露或者系统被黑客攻击,那就是危机企业存亡的灾难性问题。
因此公司的所有人员都必须对系统的安全性提高警惕。
系统的安全管控是一个非常庞大的话题,这里主要从开发人员的角度来谈一下需要注意的一些事项。
网站一定要启用HTTPS,从而避免网站内容被运营商劫持,以及避免网站通信被窃听。
Web服务器一定要只开放Web服务的端口,其他端口不要开放。
如果运维人员需要通过远程桌面或者SSH连接到服务器,那么一定要在服务器的防火墙上设置只允许运维人员的IP段访问相关端口。
要启用负载均衡服务器。
这样恶意攻击者就只知道负载均衡服务器的IP地址,而不知道Web服务器的IP地址,降低恶意攻击者直接访问Web服务器的安全风险。
要启用WAF(Web application firewall),WAF可以阻挡相当一部分潜在的网络攻击。
数据库服务器只允许Web服务器的IP地址访问;
数据库服务器一定要设置定时自动备份机制,并且把备份文件异地保存,以便在出现问题时及时恢复数据。
严格区分开发环境和生产环境,增强生产环境的访问权限管理,避免开发人员直接访问生产环境的服务器。
对开发人员的代码进行审查,特别要防范CSRF(cross-site request forgery,跨站请求伪造)、XSS(cross site scripting,跨站脚本攻击)、SQL注入漏洞、请求重放攻击等。
不要相信客户端提交的任何数据,要对客户端提交的数据进行校验,因为客户端提交的数据有可能是造假的。
比如我们要实现”删除评论”的功能,我们限定”只有评论的作者才能删除自己发表的评论”,如果我们只是在非当前用户发表的评论中不显示”删除评论”链接的话,恶意用户就可以直接找到删除评论的链接,然后把其他人发表的链接的ID拼接到”删除评论”的链接中,从而删除其他人发表的评论。
应对这样的漏洞的解决方案就是在所有操作中都要对请求的数据进行校验,比如在”删除评论”操作中,我们就要校验被删除的评论是否是当前用户发表的。
防范关键业务数据的”可预测性“。
如果我们用自增值作为订单的主键的话,竞争对手就可以从订单的主键推测出我们的业务量,而且竞争对手也可以通过对订单主键值的简单递增遍历来批量抓取数据。
这个问题的解决方案就是用Guid等不可预测的值作为主键值。
避免服务器端发送给客户端的报错信息造成的泄密,尽量不要把服务器内部的细节发送给客户端。
比如我们不能直接把服务器端的异常堆栈发送到客户端,因为异常堆栈中可能包含系统重要的技术秘密,甚至可能包含数据库的连接配置等信息。
再如,登录失败给客户端的报错信息应该是”用户名或密码错误”这样比较笼统的信息,如果服务器端给客户端的报错信息是”用户名不存在”,那么就会给恶意攻击者通过这个报错信息猜测合法用户名的机会。
特别应该注意的一个问题是,我们不要直接把EF Core中的实体类对象作为请求的响应报文体,因为实体类对象中可能包含一些不应该发送给客户端的数据。