1. htmlspcialchars strip_tags 不能预防 XSS
little: 能防一部分, XSS 的目的主要是插入他的代码并执行,储蓄,反射都是一样的目的
htmlspecialchars、strip_tags只适用于php模板渲染页面的情况。还有一些这个处理不了,比如 页面数据是从 api接口来的,api接口返回了json串,里面带有 <,而你的页面直接把这个api的某个json key数据 $.html() 插入页面了,这还是会xss.
你总不可能在api输出的时候,每个json key,还有多维深度的key,都做htmlspecialchars吧
比如 <a href="{{ $url }}" title="{{ $title }}">,这个 {{ $title }} 相当于 htmlspecialchars($title),如果你的 $title 变量被精心构造过,例如值是 标题"<script 这样的,提前结束.
安小超: 我们通常谈论防 xss 是说写入阶段,因为如果我引入第三方 api 那前提我们对第三方是信任的,第三方通常是有名气的或者合作方,至少他们肯定不会产生这种攻击行为
littile: 我就不喜欢在写入阶段防 XSS。我认为数据库里一定要保留原始的用户输入数据,不管他是安全的还是非安全的。根据不同的使用场景做不同的转义。
比如大多数页面模板输出,那就用 htmlspcialchars 转义。如果放在 html 属性里,就还需要对 引号特殊处理。如果是放在 客户端的api,那只需要 json/xml 转义,不需要 html 相关的转义,客户端不可能存在放个 < 就挂了呀。
安小超: 其实这个与业务相关,比如文章内容,显然是可以在写入阶段就过滤掉不需要的东西的,评论也是如此,但是像有的支持在后台定义模板的,必然不能这样搞.
littile: 一般文章、评论是预编译、预转义,而用户名、姓名、昵称这些是直接限制,只允许特定的字符。其他的鬼字段就是显示的时候处理了,你填个双引号就给你显示双引号,填个SQL就给你显示SQL,无所谓的,保持原样,但安全转义过.
安小超: 嗯,如果说前端就是 {{ }} 就不怕了
2. 分库分表
问: 假设有很多用户,分user1 ,user2 ,user3,添加用户添加到那一个表,怎么弄的
安小超: 看你的 hash 方案 ,有无数种方案,最简单的一个方案就是按一个唯一字段 hash, 比如按 id 后几位取余,尾号为 9 的在 user_9,分库分表的时候你就需要一个 id 生成服务了.
七爷: 而且id还必须能换算得到具体的表和库
little: 千万条记录以内,没必要分表
曹毅: 看具体怎么hash的就行,一般就是根据用户id的尾号, 确定某个用户在哪个表里,你必须知道分表的算法, 一般就是假如有uid 1,2,3,4,5,6,7,8,9 的九个用户,分成九个表,这九个表的表名就是user_1, user_2....
little:id hash分表,就只能按id查询,不能按某个跨多个表的字段查询。不要想着又想按id查询,又想按字段查询
安小超: 分表其实并不是一个好的解决方案, 它只适合用于存储个人资料类似的东西, 所以要么用中间件,要么用 MySQL 自带的分片, 否则你的代码量会增大好多,复杂好多, 感觉纵向分表比横向在查询这件事情上逻辑复杂度低好多, 比如文章,只有内容字段比较占空间, 把它弄出去,分表,按文章 ID hash, 这样一来,文章表就不用分表了, 查询全都发生在文章表上, 文章内容表只是显示的时候按主键提取内容, 一条文章记录,内容字段占了 99% 的空间吧
little: 好的解决办法是怼硬件。分片也差不多,只是业务层代码量小一点。不要跨分片查询,跨分片查询性能也是渣渣。单表亿级数据以内,都是 MySQL SSD,加个索引足够了
数据量小的表,无需分。加点硬件、加缓存。数据量太大的表,基本上要横向纵向分表同时考虑。把需要索引搜索的,放小表不分表。其他大字段放大表,只按主键id查询,并且横向hash分表。
安小超: 不需要列表展示的好说,一旦需要列表展示,比如 feed 流, 哈哈横向就尴尬了
3. 并发方面
龙权: 觉得就两个方面, 1 队列, 2 锁机制
little: 锁了并发就是1了
提高单机QPS是一方面,另一方面数据不要存服务器本地这样才能分布多台机器无状态同时服务。
锁他干什么?这与你的命题不一致啊。锁是屏蔽无效请求,你提的问题是如何提高并发能力,那就是怎么做到瞬间能成功处理更多的请求。
河子: 缓存, 层次化的缓存架构设计
little: L1、L2、L3多级缓存, 浏览器、CDN、页面cache、数据cache等等, 单机QPS上去了,能分布式部署。那自然总体的并发能力就可以提高。简单说,就是尽可能让单次请求php执行时间尽可能短。
王杨: 集群队列抗写入, 分布式集群消费队列,比如kafka,比如redis的list,比如memcache的mcq, 都是队列
little: 队列是好,在于处理复杂的任务。但是也有不好,工作有延迟不会即刻反馈执行结果。加了队列,无论是产品页面还是技术架构都会复杂一些。
王杨: 队列利于解耦,利于处理大并发,web开发就免了,能用队列的地方不多
little: 同步别用队列,用了队列不考虑同步,这完全是互斥的
问: 怎么避免超卖?
王杨: 用队列可以实现, 卖几个pop几个就是了, 发和一致性问题都交给队列层自己搞定了
队列本身就是有序的, push入队列是有先后顺序的
4. 限制无效请求
限制无效请求,增加crsf和页面js控制,再严格一点就做一个通用计数器组件,再多那就上waf,
关于 file watch 监测不到文件变化
结论就是:import 路径是不区分大小写的,但是 file watch 是大小写敏感的
因为我今天找了大神过来帮忙看,我就演示说: “就 TM vue 文件检查不到变化” (此时我在一个非 Goods 目录修改 vue),这时候,奇葩的一幕出现了,检测到变化了 , 然后我就回到 goods 目录修改,发现检测不到, 我就知道了 goods 目录出事儿了, 然后我以为是目录权限问题, 对比了一下是一样的, 然后大神提了一句:是不是这些文件没被引用啊?????第一反应是不可能!因为页面我都看到了, 然后我就顺势打开了 router,发现了惊人的一幕:goods 大写了!!!
import from 本来就不区分大小写,所以直接手动编译是 OK 的,也不报错, 但是 file change 的时候,对比不相等啊哈哈 goods != Goods
文件上传安全
判断文件后缀就安全了? navie
难道不应该检查文件后缀,检查文件体积,读取文件头信息检查图片格式,限制图片宽度、高度。然后抽掉exif文本信息,强制压缩(即使产品需要原图也是1:1和原图相同的宽度高度压缩)。