# PHP 版本
请在 2019 年使用 PHP 7.2, 并且计划 2019 中期切换到 PHP 7.3
到目前为止(2018-01-19),PHP 7.2 已经发布快两个月了。
7.1 以下版本已进入 LTS 养老末期,使用低版本的 PHP 意味着没有官方的安全维护,
也无法使用新特性和更快的速度(例如 PHP 内置加密操作 PASSWORD_HASH() 仅支持 PHP >= 5.5 ,
和大多数软件一样,PHP 通常会提供 LTS 长期支持和维护,
但是因为无法知道安全补丁的版本号,不像 Windows 操作系统一样,安全补丁有据可查, 这会使得产品的安全性大大降低。
因此,如果你是新开的项目,请使用 PHP 最新版本,而过旧的项目也要尝试重构更新。
## 依赖管理
> Composer 安装、配置及使用请参考本书 第二章:2.3 开发环境搭建
Composer: https://getcomposer.org/ 在 PHP 生态中是重要的一环,大部分的扩展包都是通过 Composer 进行管理。
如果你是手动下载扩展包并进行手动加载,那么在大型应用上,你无法检测某个框架是否过时,
也无法知晓某个框架的重大安全漏洞并及时更新到最新版本,过老的版本是非常不安全的。
## HTTPS 和浏览器安全
HTTPS,一种通过计算机网络进行安全通信的传输协议
在 2018 年,所有现代安全的浏览器已经不在接受 HTTP,用户打开 HTTP 协议的网站时,
浏览器会警告该网站的连接不安全。
不过你可以从各大云厂商免费的申请一个 TLS 证书, 或者使用 Let's Encrypt certificate authority: https://letsencrypt.org/ .
## 开发安全的 PHP 程序
避免 PHP 程序存在 SQL 注入
如果你是自己编写 SQL 代码, 请确保使用 prepared 语句,
并且从网络或文件系统提供的信息都作为参数传递, 而不是字符串拼接的形式。
此外,确保你没有使用 模拟的 prepared 语句: https://stackoverflow.com/questions/134099 .
## 文件上传处理
接受未知来源的问题,意味着这些文件可能恶意攻击服务器,
请保证服务器文件权限不超过 775,
上传的新文件应该是 只读或读写,
不要在网站根目录保存文件,
同大多数 PHP 框架一样,不在根目录运行 index.php 目的是为恶意代码提供最少的执行环境,
例如:
` /var/www/example.com-uploaded/ `
或者直接将文件往下移动一个层级
` /var/www/example.com/public `
## 跨站请求伪造
跨站请求伪造(CSRF)是一种混淆的代理攻击,通过诱导用户的浏览器代表攻击者执行恶意的 HTTP 请求(使用的是该用户的权限).
首先使用 HTTPS,没有 HTTPS 的话,任何保护都是脆弱的,因为所有数据都是明文传输。
如果你是用的是现代 PHP 框架,请在框架中开启 CSRF 验证
如果你是原生用户,只需要:
* 增加基本的 Challenge-response authentication。
* 为每个表单添加一个隐藏的表单属性。
* 填充一个密码安全的随机值(称为令牌).
* 验证是否提供了隐藏的表单属性,以及是否匹配上期望值。
## 密码散列
>安全的密码存储曾经是一个激烈争论的话题,但现在实现起来相当微不足道
~~~~
$hash = password_hash($password, PASSWORD_DEFAULT);
if (password_verify($password, $hash)) {
// Authenticated.
if (password_needs_rehash($hash, PASSWORD_DEFAULT)) {
// Rehash, update database.
}
}
~~~~
甚至不需要知道在后台使用什么算法,因为如果你使用最新版本的 PHP ,你也将使用当前最新的技术,用户的密码将会自动进行升级(只要有新的默认算法可用).
无论你做什么,都不要做 WordPress 所做的事情
WordPress 并不使用 bcrypt 来储存密码,而是使用 MD5,
要理解为什么,首先查看 这个代码片段 以及 这一个
如果 $this->portable_hashes 设置为TRUE,则会调用 $this->crypt_private()
因此,HashPassword 可以大大简化为以下片段:
~~~~
function HashPassword($password)
{
if ( strlen( $password ) > 4096 ) {
return '*';
}
/* these steps are skipped */
$random = $this->get_random_bytes(6);
$hash =
$this->crypt_private($password,
$this->gensalt_private($random));
if (strlen($hash) == 34)
return $hash;
return '*';
}
~~~~
- 第一章. 基础信息
- 1.1 序言
- 1.2 关于作者
- 1.3 本书源码
- 1.4 反馈纠错
- 1.5 安全指南
- 1.6 捐助作者
- 第二章. 开发环境布置
- 2.1 编辑器选用
- 2.2 命令行工具
- 2.3 开发环境搭建
- 2.4 浏览器选择
- 2.5 第一个应用
- 2.6 Git 工作流
- 第三章. 构建页面
- 3.1 章节说明
- 3.2 静态页面
- 3.3 Think 命令
- 3.4 小结
- 第四章. 优化页面
- 4.1 章节说明
- 4.2 样式美化
- 4.3 局部视图
- 4.4 路由链接
- 4.5 用户注册页面
- 4.6 集中视图
- 4.7 小结
- 第五章. 用户模型
- 5.1 章节说明
- 5.2 数据库迁移
- 5.3 查看数据表
- 5.4 模型文件
- 5.5 小结
- 第六章. 用户注册
- 6.1 章节说明
- 6.2 注册表单
- 6.3 用户数据验证
- 6.4 注册失败错误信息
- 6.5 注册成功
- 6.6 小结
- 第七章. 会话管理
- 7.1 章节说明
- 7.2 会话
- 7.3 用户登录
- 7.4 退出
- 7.5 小结
- 第八章. 用户 CRUD
- 8.1 章节说明
- 8.2 重构代码
- 8.3 更新用户
- 8.4 权限系统
- 8.5 列出所有用户
- 8.6 删除用户
- 8.7 访客模式
- 8.8 优化前端
- 8.9 小结
- 第九章. 微博 CRUD
- 9.1 章节说明
- 9.2 微博模型
- 9.3 显示微博
- 9.4 发布微博
- 9.5 微博数据流
- 9.6 删除微博
- 9.7 小结