一、概述

1、相对来说,Java是一种较为安全的语言:

1)没有显式的指针操作

2)对数组和字符串边界有自动检查机制

3)如果尝试引用一个空指针会抛出系统异常

4)算术运算是明确定义的且与平台无关,类型转换也是如此。

5)内置的字节码验证器可以确保这些检查会在正确的地方执行

 

二、输入验证和数据净化(IDS)

1、sql注入,使用PreparedStatement

2、xml注入,正则验证(白名单),xml模板

3、字符串验证前(如正则验证),先标准化字符串:Normalizer.normalize()

4、文件路径使用之前,先标准化路径名:file.getCanonicalPath()。然后检查路径名的安全性,比如是否在所允许访问的目录里

5、传递给ZipInputStream的文件应该限制大小

6、使用ASCII字符集的子集作为文件名和路径名,正则表达式:

Pattern pattern = Pattern.compile("[^A-Za-z0-9%&+,.=_]");
Matcher matcher = Pattern.matcher(filename);
if(matcher.find()){
//filename contains bad chars, handle error
}

7、不要向Runtime.exe()方法传递非受信、未净化的数据:正则过虑、通过switch选择(可以通过属性文件读入到java.util.Properties对象中)、避免使用Runtime.exec()

8、如果正则表达式的匹配模式中,有用户输入的字符,则需要对用户输入的字符进行净化。Character.isLetterOrDigit(char ch)

9、如果没有指定适当的locale,不要使用locale相关方法处理与locale相关的数据。

正例:

1)"title".toUpperCase(Locale.ENGLISH);
2)Locale.setDefault(Locale.ENGLISH);
"title".toUpperCase();

10、避免拆分多字节字符

1)

java语言支持安全性吗 java语言安全编程规范_字符串

 

2)使用Reader

3)了解一下这两个类:java.text.BreakIterator、java.text.Collator

11、在验证前去掉非字符码点(自己实际编码,测试未通过)

12、在不同的字符编码中无损转换字符串数据时,通过CharsetEncoder和CharsetDecoder两个类来处理编码转换问题。写文件时可以给OutputStreamWriter传入CharsetEncoder参数

13、byte数组转化成String时,需指定字符编码,如:String result = new String(byteData,"UTF-8")

 

 

三、声明和初始化

1、防止类的循环初始化,正例:

java语言支持安全性吗 java语言安全编程规范_java语言支持安全性吗_02

2、避免类间的静态变量循环引用

3、不要重用Java标准库的已经公开的标识

4、将所有增强for语句的循环变量声明为final类型;给增强型的for循环变量赋值,不影响整体的迭代次序。

正例:

for(final Obj obj : objList){
}

 

四、表达式

1、不要忽略方法的返回值。如:

1)不可变对象需要重新赋值

2)判断方法返回结果是否为true

2、不要解引用空指针,注意对null的判断

3、数组不会重写Object.equals()方法,而equals()方法比较的是数组引用而不是数组的内容值。程序必须使用两个参数的Arrays.equals()方法来比较两个数组的内容。当想要测试引用是否相等时,程序必须使用引用相等操作:==或!=

4、不要用相等操作来比较两个基础数据类型的值。会被内存化的基础结构数据:如果要封装的p的数值是true、false、一个字节、一个在\u0000 ~ \u007f范围的char,或者是一个位于-128 ~ 127的int或short数据。

5、确保使用正确的类型来自动封装数值

6、不要在一个表达式中对同一变量进行多次写入

7、不要在断言中使用有副作用的表达式

 

五、数值类型与运算

1、检测和避免整数溢出

1)先决条件检测,通过Integer.MIN_VALUE和Integer.MAX_VALUE

2)

java语言支持安全性吗 java语言安全编程规范_字符串_03

java语言支持安全性吗 java语言安全编程规范_数据_04

3)向上类型转换

java语言支持安全性吗 java语言安全编程规范_数组_05

4)使用BigInteger的方法来检测溢出

5)使用AtomicInteger时,应该通过get()方法判断当前值,符合计算要求后再通过compareAndSet()方法设置新值

2、不要对同一数据进行位运算和数学运算

3、确保除法运算和模运算中的除数不为0。注意:当被除数等于有符号整数的最小值并且除数是-1时,也会发生溢出

4、使用可容纳无符号数据合法取值范围的整数类型

5、不要使用浮点数进行精细计算

1)金额可以用分为单位进行计算

2)也可以使用BigDecimal,但是会有性能损失

6、不要使用非标准化数,用double类型进行浮点数计算

7、使用strictfp修饰符确保跨平台浮点运算的一致性

8、不要尝试与NaN进行比较。可以通过Double.isNaN(result); 来检测result是否是NaN

9、检查浮点输入特殊的数值。三种特殊的数值:无穷大、无穷小和NaN。

java语言支持安全性吗 java语言安全编程规范_java语言支持安全性吗_06

10、不要使用浮点变量作为循环计数器

11、不要从浮点字元构造BigDecimal对象。

正例:new BigDecimal("0.1");

反例:new BigDecimal(0.1);

12、不要比较或者审查以字符串表达的浮点数值

13、确保将数值转换成较小类型时不会产生数据丢失或曲解。转换之前做数值范围检查。

14、转换基本整数类型至浮点类型时应避免精度损失