在日常编码中,基本上99%的项目都会有一个DateUtil工具类,而时间工具类里用的最多的就是java.util.Date。
大家都这么写,这还能有问题??
当你的“默认常识”出现问题,这个打击,就是毁灭性的。
但是,在进行安全扫描的时候,提示java.util.Date存在安全漏洞。
public class DateUtil {
/**
* 日期格式化
*/
public static String formatDate(Date date, String format) {
SimpleDateFormat sdf = new SimpleDateFormat(format);
return sdf.format(date);
}
/**
* 字符串转Date
*/
public static Date parseDate(String dateStr, String format) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat(format);
return sdf.parse(dateStr);
}
/**
* 获取指定格式的当前时间
*/
public static String getCurrentDate(String format) {
// 获取当前时间
Date currentDate = new Date();
// 定义日期格式
SimpleDateFormat dateFormat = new SimpleDateFormat(format);
return dateFormat.format(currentDate);
}
}
把组件风险列表截图+DateUtil工具类发给我的编程小助手ChatGPT4o。
Prompt:在进行安全扫描的时候,提示java.util.Date存在安全漏洞,有什么漏洞,如何解决?
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.Date;
public class DateUtil {
// 日期格式化
public static String formatDate(LocalDateTime dateTime, String format) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
return dateTime.format(formatter);
}
// 字符串转Date
public static LocalDateTime parseDate(String dateStr, String format) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
return LocalDateTime.parse(dateStr, formatter);
}
// 获取指定格式的当前时间
public static String getCurrentDate(String format) {
// 获取当前时间
LocalDateTime currentDate = LocalDateTime.now();
// 定义日期格式
DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern(format);
return currentDate.format(dateFormat);
}
// 将 java.util.Date 转为 java.time.LocalDateTime
public static LocalDateTime convertToLocalDateTime(Date date) {
return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
}
// 将 java.time.LocalDateTime 转为 java.util.Date
public static Date convertToDate(LocalDateTime dateTime) {
return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
}
}
以下是Date设计上的主要缺陷:
- Date 这个名称本身就具有误导性。它实际上表示的是一个时间点,而非日期。因此,更为恰当的名称应为 Instant,这与 java.time 中的对应类型相符。
- 它不是一个最终类,这导致了诸如 java.sql.Date 等不良的继承使用。java.sql.Date 旨在表示一个日期,但由于名称相同而常常引起混淆。
- Date 是可变的,而日期/时间类型通常是自然值,适合用不可变类型进行建模。Date 的可变性(例如通过 setTime 方法)迫使开发人员不得不创建大量防御性副本,以确保代码的安全性。
- Date 在许多地方(包括 toString() 方法)隐式使用系统本地时区,这常常让开发人员感到困惑。更多细节可以参见“时间点是什么”部分。
- Date 的月份编号从 0 开始,这是借鉴自 C 语言的设计。这种设计导致了大量的“偏一”错误。同样,年份编号从 1900 开始,也是借鉴自 C 语言。显然,当 Java 出现时,我们已经意识到这种设计不利于代码的可读性。
- Date 的方法命名也不清晰。getDate() 方法返回的是月中的某一天,而 getDay() 方法返回的是星期几。给这些方法起更具描述性的名称并不会很困难,但遗憾的是,这并未实现。
- 对于是否支持闰秒,Date 的表现也不明确。文档中指出“一秒钟由一个 0 到 61 的整数表示;60 和 61 仅在实际正确跟踪闰秒的 Java 实现中出现。” 我强烈怀疑,大多数开发人员(包括我自己)都默认认为 getSeconds() 方法的返回值范围是 0-59。
- Date 类的方法对参数范围的要求非常宽松,这没有明显的理由。例如,方法允许日期参数为 1 月 32 日,并解释为 2 月 1 日。这种宽松的参数范围在实际应用中并不常见,反而增加了使用的复杂性和出错的风险。
尽管还能找到更多的问题,但那会显得过于挑剔。