阿里编码规范的一个小视频,以下内容都来源自该视频
https://www.bilibili.com/video/BV1DE411i7xP?from=search&seid=10419419802261821693
关于字段检验的规范
-
【强制】隶属于用户个人的页面或者功能必须进行权限控制校验。
说明:防止其他人随意访问、修改和删除数据;前后端最好都校验。 -
【强制】用户敏感数据禁止直接展示,必须对展示数据进行脱敏,防止泄露隐私。
例子:手机号显示为:137****7456,隐藏部分数据;数据库等明文(密码)也要加密。 -
【【强制】用户输入SQL参数严格使用参数绑定,或者METADATA字段值限定,防止SQL注入(字符串拼接访问数据库)。
说明:mybatis框架有防止依赖注入的措施。SQL语句中少用或不用"$"绑定参数。 -
【强制】用户请求传入的参数必须做有效性验证,例如在框架层都要做特殊字符过滤(大于号,小于号,单引号)。
说明:忽略参数校验可能导致:page size过大导致内存溢出;
恶意order by导致数据库慢查询;
任意重定向;
SQL注入;
反序列化注入;
正则输入源串拒绝服务 ReDos。 -
【强制】禁止向HTML页面输出未经安全过滤或未正确转义的用户数据。
说明:系统的出入口要堵住特殊字符:出口一般是指web界面;入口指的是web界面,也可能是接口。 -
【强制】表单、AJAX提交必须执行CSRF安全验证:
- 检查Referer字段(Header中的信息,仅需在关键处增加一步校验;简单易行)
- 添加校验token(服务器一个伪随机数,作为参数一并提交以供校验;有一定工作量,也更有效)。
说明:CSRF跨站请求伪造是一类常见的编程漏洞。攻击者可以事先构造URL,只要受害者用户一访问,后台便在用户不知情的情况下对数据库中的用户参数进行相应修改(欺骗用户浏览器,让浏览器以用户的名义运行操作)。
-
【强制】使用平台资源(短信、邮件、电话、下单、支付)时,必须实现防重放机制,避免滥刷而导致资损。
说明:数量限制、疲劳度控制、验证码校验等。
- 一个手机号一天只能接收三次短信验证
- 第二次刷新添加或下单接口防重放
- 【强制】评论、发帖、即时消息等场景必须实现防刷、文本内容违禁词过滤等风控策略。
说明: 违禁词控制
MySQL数据库
安全约规
- 【强制】表达【是、否】概念字段,必须使用is_xxx方式命名,数据类型是unsigneed tinyint(1代表是,0代表否)
说明: 非负数必须用unsigned;POJO类中的任何布尔值变量,都不加is前缀。定义为基本数据类型boolean isSuccess;的属性,它的方法也是isSuccess(),RPC 框架在反向解析的时候,“以为”对应的属性名称是success,导致属性获取不到,进而抛出异常。 - 【强制】表名、字段名必须使用小写字母或数字;禁止出现数字开头,禁止两个下划线中间只出现数字。表名称不使用复数名词。
说明: 数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。
正例:getter_admin, task_config, level3_name
反例:GetterAdmin, taskConfig, level_3_name - 【强制】禁止使用保留字,如desc、range、match等。
说明: 所有数据库中命名都不允许用关键字。 - 【强制】唯一索引名为uk_字段名;普通索引名则为idx_字段名。
说明: uk_即unique key;idx_即index的简称。 - 【强制】小数类型为decimal,禁止使用float和double。
说明:float和double在存储的时候,存在精度损失的问题,很可能在值的比较时,得到不正确的结果。如果存储的数据范围超过decimal的范围,建议将数据拆成整数和小数分开存储。 - 【强制】如果存储的字符串长度几乎相等,使用cha定长字符串类型。
说明:存储11位的手机号。 - 【强制】varchar是可变长字符串,不预先分配存储空间,长度不要超过 5000,如果存储长度大于此值,定义字段类型为text,独立出来一张表,用主键来对应,避免影响其他字段索引效率。
- 【强制】表必备三字段:id,gmt_create,gmt_modified。
说明:其中id必为主键,类型为unsigned bigint、单表时自增、步长为1;gmt_create和gmt_modified的类型均为date_time类型。。 - 【推荐】表的命名最好遵循“业务名称_表的作用”。
说明: 例如alipay_task,看起来比较清晰方便。 - 【推荐】库名与应用名称尽量一致;
- 【推荐】如果修改字段含义或对字段追加状态,要及时更新字段注释。
- 【推荐】字段允许适当冗余,以提高查询性能,但必须考虑数据一致性。比如遵循:不是频繁修改字段;不是varchar超长字段;不是唯一索引字段等。
- 【推荐】单表行数超过500万行或者容量超过2GB,才推荐进行分库分表。
说明:如果预计三年后数据量达不到这个级别,就不要分库分表。 - 【推荐】合适的字符存储长度,可以节约数据库表空间、节约索引存储,最重要的是提升检索速度。
说明:不能一味地节约空间,要结合具体场景,比如字段预留一定长度防止溢出。
索引规约
- 【强制】业务上具有唯一特性的字段,即使是组合字段,也必须建成唯一索引。
说明:不用以为唯一索引影响了insert速度,这个速度损耗可以忽略,但提高查找速度是明显的;另外,即使在应用层做了非常完善的校验和控制,只要没有唯一索引,根据墨菲定律,必然有脏数据产生 - 【强制】 超过三个表禁止join。需要join的字段,数据类型保持绝对一致;多表关联查询时,保证被关联的字段需要有索引。
说明:即使双表join也要注意表索引、SQL 性能。 - 【强制】在varchar字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度。
说明:索引的长度与区分度是一对矛盾体,一般对字符串类型数据,长度为 20 的索引,区分度会高达 90% 以上,可以使用count(distinct left(列名,索引长度))/count(*)的区分度来确定。 - 【强制】页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。
说明:索引文件具有B-Tree的最左前缀匹配特性,如果左边值未确定,就无法使用此索引。 - 【推荐】如果有order by场景,请注意利用索引的有序性,应该放在索引组合顺序的最后,避免引发查询性能问题。
说明:索引如果存在范围查询,那么无法利用索引的有序性。 - 【推荐】利用覆盖索引来进行查询操作,避免回表。
说明:能够正确建立索引的种类:主键索引、唯一索引、普通索引,用explain的结果,extra列表会出现:using index。 - 【推荐】利用延迟关联或子查询优化超多分页场景。
说明:mysql并不是跳过offset行,而是取offset+N行,然后放弃offset,返回N;当offset很大时,查询效率就非常低。 - 【推荐】SQL性能优化目标:至少达到range级别,要求是ref级别,consts级别最好。
说明:consts单表最多只有一个匹配行(主键或唯一搜索)
ref指的是普通索引,range是指对索引进行范围检索 - 【推荐】防止因字段类型不同造成的隐式转换,导致索引失效。
- 【参考】创建索引时:宁缺毋滥
SQL语句
- 【强制】不要用count(常量,列名)来代替count(*),后者是跟NULL或非NULL无关的。
说明: count( *)是会统计NULL行的。 - 【强制】count(distinct col)计算该列除 NULL 之外的不会重复数量。注意count(distinct col1, col2)如果其中一列全为 NULL,那么即使另一列有不同的值,也返回为0。
- 【强制】当某一列的值全是NULL时,count(col)返回0;但是sum(col)返回NULL。
说明:sum(col)时,注意NPE问题,即空指针异常。 - 【强制】使用isNULL()来判断是否为空值。
说明:null与任何值比较都是null。 - 【强制】代码中写分页查询逻辑时,若count为0应直接返回,避免执行后面的分页语句。
- 【强制】不得使用外键与级联,一切外键 概念必须在应用层解决。
- 【强制】数据订正(删除、修改)时,要先select,避免出现误删除,确认无误才能执行更新语句。
- 【推荐】in操作能避免就避免。
ORM映射
- 【强制】查询表时,一律不要以作为查询字段,需要具体写明查询的字段。
说明: 用会增加查询分析器的解析成本;增加消耗。 - 【强制】不要用resultClass当返回参数,即使所有类属性名与数据库字段一一对应,也需要定义;反过来,每一个表也必然有一个与之对应。
说明: 配置映射关系,使字段与 DO 类解耦,方便维护。 - 【强制】ibatis自带的queryForList()不推荐使用。
说明: 实际开发中基本上用limit。 - 【强制】不允许直接拿HashMap与Hashtable作为查询结果集的输出。因为值的类型不可控。
- 【强制】更新表记录时,必须更新记录对应的gmt_modified字段值为当前时间。