盘点开发者容易忽略的安全问题,包括硬编码API密钥、信任用户输入、API返回过多数据、密码存储不当等,并给出修复建议。
在构建应用程序时,很容易只关注功能是否正常工作。
登录可以用了。API 返回了数据。支付页面加载成功。
但安全问题往往隐藏在我们忽略的地方。
我见过一些开发者犯下这些错误,仅仅是因为他们想让应用程序先跑起来。下面是一些值得检查的问题。
把这样的东西直接写在源代码里,就是自找麻烦:
API_KEY = "your-secret-key"
即使你之后删除了,密钥仍然可能存在于 Git 历史中。
改用环境变量或专业的密钥管理器。
如果密钥已经泄露,不要只是删除那一行。要轮换(rotate)密钥。
永远不要假设来自用户的数据是安全的。
用户名、邮箱地址、搜索查询、上传的文件或表单字段都可能包含意外输入。
在服务端验证输入,使用适当的输出编码和参数化查询。
客户端验证对用户体验有帮助,但不应作为唯一的安全控制手段。
有时候 API 返回整个数据库对象,而前端只需要两个字段。
{ "name": "John", "email": "john@example.com", "password_hash": "...", "internal_id": 12345 }
前端可能只需要姓名和邮箱。
只返回客户端实际需要的数据。
这能减少意外的信息泄露。
身份验证(Authentication)回答的是:
"你是谁?"
授权(Authorization)回答的是:
"你有权做这件事吗?"
用户登录了,不代表他们可以访问所有资源。
GET /api/users/102/profile
服务器应该验证当前用户是否有权访问那个档案。
不要依赖在前端隐藏按钮。
后端需要强制执行权限。
密码绝对不能明文存储。
如果数据库被攻破,明文密码立刻成为一个大问题。
使用专门为密码存储设计的哈希算法,如 Argon2id、bcrypt 或 scrypt,并进行适当的配置。
请记住:加密和密码哈希不是一回事。
HTTP 安全响应头可以提供另一层保护。
根据你的应用程序,考虑使用以下响应头:
你不必盲目地添加每一个响应头。
理解每个响应头的作用,按应用程序的需求进行配置。
调试工具在开发过程中很有用。
它们也可能暴露敏感信息。
部署到生产环境之前,检查你的应用程序是否意外暴露了:
生产环境不应表现得像本地开发环境。
你不需要成为渗透测试人员才能开始测试应用程序的安全性。
试着问一些简单的问题:
这些基本检查可以发现意想不到的严重问题。
在将应用程序推送到生产环境之前,花几分钟检查:
安全不是应用程序完成后才添加的东西。
越早考虑安全性,就越容易自然地将它融入应用程序中。
你不需要在第一天就掌握所有安全技术。先从理解应用程序如何处理输入、身份验证、授权、数据和错误开始。
仅这五个领域就能教你很多安全开发的知识。