书库技术与未来Java安全编码指南
书籍封面

Java安全编码指南

作者 未知
20.0 分钟

摘要

Java安全编码规范总结

本规范旨在提升Java代码的安全性、可读性和可维护性,涵盖命名、格式、面向对象、集合、并发、流量控制、注释、异常、日志、MySQL、项目结构和安全等多个方面。遵循这些规范能有效降低代码缺陷,保障系统稳定,并提高开发效率。

你能获得:

  • 代码质量显著提升
  • 系统安全性增强
  • 团队协作效率提高
  • 潜在安全漏洞最小化

核心内容:

1. 编程规范:

  • 命名约定: 强制使用英文,类名大驼峰,方法名小驼峰,常量全大写,避免魔法值。
    • 详细解释:统一的命名规范能大幅提升代码可读性,降低理解成本。例如,MAX_STOCK_COUNTMAX_COUNT更清晰。
    • 行动建议:使用IDE的代码格式化功能,自动检查命名是否符合规范。
  • 常量: 根据作用域放在不同的常量类中。
    • 详细解释:避免常量类过于庞大,难以查找和维护。
    • 举例:与缓存相关的常量放在CacheConsts,配置相关的放在ConfigConsts
  • 格式样式: 统一缩进、换行和空格使用,列数限制为120字符。
    • 详细解释:统一的代码风格能够显著提高代码的可读性,减少视觉疲劳。
    • 行动建议:配置IDE的代码格式化模板,自动调整代码风格。

2. 面向对象规则:

  • 静态成员: 通过类名引用,而非对象名。
    • 详细解释:静态成员属于类,使用类名引用更明确。
  • 重写: 使用@Override注解。
    • 详细解释:确保正确重写父类或接口方法,避免意外错误。
  • equals方法: 使用常量或非null对象调用,避免NullPointerException
    • 详细解释:保证equals方法的可靠性。
  • 浮点数比较: 指定误差范围,不能直接使用==equals
    • 详细解释:浮点数精度问题可能导致直接比较结果不准确。
  • POJO类: 不赋默认值。
    • 详细解释:提醒使用者显式赋值,避免自动装箱导致的NullPointerException风险。
  • toString方法: 必须实现,方便运行时检查属性值。
    • 详细解释:便于快速定位问题。

3. 集合:

  • hashCode和equals: 覆盖equals必须覆盖hashCode,保证Set和Map的正确使用。
    • 详细解释:确保集合中对象的唯一性和查找效率。
  • keySet/values/entrySet: 返回的集合对象不要添加或删除元素。
    • 详细解释:避免UnsupportedOperationException
  • toArray(T[] array): 列表转数组时,输入数组大小应与列表相同。
    • 详细解释:避免ClassCastException和数组元素为null的问题。
  • Arrays.asList: 数组转列表后,不能修改列表。
    • 详细解释:asList返回的是Arrays的内部类,没有实现修改自身的方法,调用add/remove/clear会抛出异常。
  • foreach循环: 不要在循环中删除或添加元素,使用Iterator。
    • 详细解释:避免ConcurrentModificationException

4. 并发:

  • 线程安全: 初始化单例实例及方法需保证线程安全。
    • 详细解释:避免资源竞争和数据不一致。
  • 线程池: 使用ThreadPoolExecutor,避免Executors的潜在问题。
    • 详细解释:Executors可能导致OOM,ThreadPoolExecutor能更精确地控制线程池参数。
  • SimpleDateFormat: 线程不安全,使用ThreadLocal或DateTimeFormatter。
    • 详细解释:避免多线程并发访问SimpleDateFormat导致的数据错误。
  • Lock: 获取锁必须放在try块之外,避免锁无法释放。
    • 详细解释:确保锁的正常释放,防止死锁。

5. 异常和日志:

  • 运行时异常: 不捕获JDK定义的运行时异常,尽可能进行预检查。
    • 详细解释:如NullPointerExceptionIndexOutOfBoundsException,通过预检查避免。
  • 异常处理: 不压制或忽略异常,顶层必须处理并翻译成用户可理解的内容。
    • 详细解释:确保异常能够被正确处理和记录。
  • 返回值: 方法返回值可以为null,明确在Javadoc中说明。
    • 详细解释:提醒调用者进行空检查,避免NullPointerException
  • 日志: 使用SLF4J,级别日志需条件输出或占位符。
    • 详细解释:提高性能,避免不必要的字符串拼接。

6. MySQL规则:

  • 命名: 表名和列名小写,避免使用关键字。
    • 详细解释:提高可读性和兼容性。
  • 索引: 超过三表不允许JOIN,连接列需索引,varchar列加索引需指定长度。
    • 详细解释:优化查询性能。
  • SQL: 不使用COUNT(column_name),COUNT(*)计算行数,使用ISNULL()检查NULL值。
    • 详细解释:保证SQL的准确性和性能。
  • ORM: 查询时指定具体列名,不用*, 布尔属性命名避免is前缀。
    • 详细解释:便于维护,避免映射问题。

7. 安全规范

  • 授权: 用户拥有的页面或功能必须经过授权. - 详细解释: 防止在未经授权检查的情况下访问和操纵他人的数据,
  • 脱敏: 不允许直接展示用户敏感数据。显示的数据必须脱敏. - 详细解释:隐藏部分重要数据,防止隐私泄露。
  • 安全检查: 用户输入的任何参数都必须经过验证校验. - 详细解释: 忽略参数检查可能会导致漏洞。
  • CSRF安全检查: 表单和AJAX提交必须经过CSRF安全检查过滤. - 详细解释:防止跨站攻击,保证请求的合法性。

问答

Q: 为什么推荐使用ThreadPoolExecutor而不是Executors创建线程池?

A: Executors创建的线程池(如FixedThreadPoolCachedThreadPool)在处理大量请求时可能会导致OOM,而ThreadPoolExecutor可以更精确地控制线程池的参数,如核心线程数、最大线程数和队列大小,从而降低系统资源耗尽的风险。

Q: 为什么要避免在foreach循环中删除或添加元素?

A: 在foreach循环中删除或添加元素会导致ConcurrentModificationException,因为foreach实际上是对Iterator的简化使用,而直接修改集合会导致Iterator的状态与集合不一致。应该使用Iterator的remove方法来删除元素。

Q: 如何正确比较浮点数?

A: 由于浮点数由尾数和指数组成,二进制无法精确表示大多数小数。因此,直接使用==equals比较浮点数是不准确的。应该指定一个误差范围,如果两个浮点数之间的差值在此范围内,则认为它们相等。

Q: 什么是覆盖索引?为什么推荐使用?

A: 覆盖索引是指查询可以直接从索引中获取所有需要的列,而不需要回表查询数据行。使用覆盖索引可以避免额外的I/O操作,提高查询性能。可以通过EXPLAIN命令查看SQL语句是否使用了覆盖索引,如果在extra列中出现using index,则表示使用了覆盖索引。

Q: 为什么建议对用户输入做验证?

A: 用户输入不经验证,可能导致多种安全问题,包括内存泄漏、数据库查询缓慢、SQL注入、反序列化注入等。严格的输入验证能够有效防止恶意用户利用这些漏洞攻击系统。

思维导图

目标读者

本规范适用于所有Java开发人员,包括初级程序员、高级工程师、架构师以及安全工程师。特别是对于那些致力于开发高安全性Java应用程序的团队,本规范具有重要的参考价值。

作者背景

该文档为Java安全编码规范,未提供作者背景信息。

历史背景

随着Java应用的广泛应用,安全问题日益突出。本规范应运而生,旨在解决Java开发中常见的安全漏洞和编码缺陷,提升Java应用的整体安全性。

章节摘要

音频

Comming Soon...