【JavaVersion+】因mysql-connector-java版本升级,引发的问题

起因

近期,我们的项目暴露出了一些问题,就像FastJSON反序列化漏洞,Tomcat拒绝服务漏洞,Shiro身份认证绕过漏洞,Apache Log4j拒绝服务漏洞,以及MySQL JDBC XXE漏洞等。当时我们以为,只需要更新一下版本,就能轻松解决问题。但是,万万没想到的是,这次的版本升级却引发了一个新的问题。

漏洞名称漏洞描述修复建议
Oracle MySQL JDBC XXE漏洞(CVE-2021-2471)Oracle MySQL 的 MySQL Connectors 产品中存在XML外部实体注入漏洞,该漏洞是由于MySQL JDBC 存在getSource()方法未对传入的XML数据做校验,导致攻击者可以在XML数据中引入外部实体,造成XXE攻击。将 mysql-connector-java 升级到 8.0.27 及以上版本,下载地址:https://mvnrepository.com/artifact/mysql/mysql-connector-java

我开始感到非常困惑,因为这让我重新审视了技术升级的风险。

问题复现

表结构
在这里插入图片描述
版本
8.0.17

{
	"code": "1",
	"data": {
		"create_time": 1641169164000
	}
}

版本
8.0.33

{
	"code": "1",
	"data": {
		"create_time": [2022, 1, 3, 8, 19, 24]
	}
}

因为我在代码里加了个通过SimpleModule,在序列化转Json时,将所有的long变成string的处理,所以会报出下面的问题。

{
	"data": {},
	"msg": "Type definition error: [simple type, class java.time.LocalDateTime]; 
	            nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type `java.time.LocalDateTime` not supported by default: 
	            add Module \"com.fasterxml.jackson.datatype:jackson-datatype-jsr310\" to enable handling (through reference chain: Result[\"data\"]->java.util.HashMap[\"update_time\"])",
	"code": -1
}

版本升级

当升级了MySQL Connector/J的版本后,从数据库读取的datetime数据类型发生了变化。原本是Timestamp类型的值,现在变成了LocalDateTime类型。

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.17</version>
</dependency>

升级后

<dependency>
	<groupId>com.mysql</groupId>
	<artifactId>mysql-connector-j</artifactId>
	<version>8.0.33</version>
</dependency>

如果想使用更高的版本,请注意groupId,artifactId的更改。这里官网给出了解释。
MySQL 连接器/J 8.1 发行说明
MySQL 连接器/J 8.1.0 中的更改(2023-07-18,正式发布)

  • Important Change: To comply with proper naming guidelines, the Maven groupId and artifactId for Connector/J have been changed to the following since release 8.0.31:
  • groupId: com.mysql
  • artifactId: mysql-connector-j
    The old groupId and artifactId can no longer be used for linking the Connector/J library starting with this release. Please make sure you switch to the new coordinates. See Installing Connector/J Using Maven. (WL #15259)

解决方案

方法一:注解指定

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") 
private Date createTime;  

只适用于在实体上添加指定。

方法二:sql格式化

DATE_FORMAT(create_time, '%Y-%m-%d %H:%i:%s') AS create_time

方法三:Jackson重写信息转换器

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@EnableWebMvc
@Configuration
public class WebDataConvertConfig implements WebMvcConfigurer {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = new ObjectMapper();
        /**
         * 序列换成json时,将所有的long变成string
         * 因为js中得数字类型不能包含所有的java long值
         */
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(Long.class, ToStringSerializer.instance);
        javaTimeModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        /* 格式化日期
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        objectMapper.setTimeZone(TimeZone.getTimeZone(ZoneId.of("Asia/Shanghai")));
        */
        objectMapper.registerModule(javaTimeModule);
        jackson2HttpMessageConverter.setObjectMapper(objectMapper);
        converters.add(jackson2HttpMessageConverter);
    }
}

在尝试将时间转换为JSON格式时,我遇到了一个令人困惑的问题。时间返回格式变成了时间戳格式或UTC时间格式,但我一直无法成功格式化它。网上搜索结果是因为spring.jackson.date-format 这个属性在spring boot 1.x中有用,但是当你项目升级到spring boot2.x 以后,时间格式化变无效了。尝试一下,没有解决,所以改用方法四,最终解决了这个问题。

{
	"code": "1",
	"data": {
		"create_time": "2022-01-03T08:19:24"
	}
}

方法四:FastJson重写信息转换器

import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.ToStringSerializer;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@EnableWebMvc
@Configuration
public class WebDataConvertConfig implements WebMvcConfigurer {

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        //创建fastJson消息转换器
        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
        //创建配置类
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        //修改配置返回内容的过滤
        fastJsonConfig.setSerializerFeatures(SerializerFeature.BrowserCompatible,
                SerializerFeature.WriteNullListAsEmpty,
                SerializerFeature.PrettyFormat,
                SerializerFeature.WriteDateUseDateFormat,
                SerializerFeature.WriteNullStringAsEmpty,
                SerializerFeature.WriteMapNullValue,
                SerializerFeature.DisableCircularReferenceDetect
        );
        //解决Long转json精度丢失的问题
        SerializeConfig serializeConfig = SerializeConfig.globalInstance;
        serializeConfig.put(Long.class, ToStringSerializer.instance);
        serializeConfig.put(Long.TYPE, ToStringSerializer.instance);
        fastJsonConfig.setSerializeConfig(serializeConfig);
        // 将配置设置给转换器并添加到HttpMessageConverter转换器列表中
        fastConverter.setFastJsonConfig(fastJsonConfig);
        converters.add(fastConverter);
    }
}

人因梦想而伟大,又因坚持梦想而成长!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: mysql-connector-javamysql-connector-j是同一个MySQL官方提供的JDBC驱动程序,它用于连接MySQL数据库和Java应用程序。mysql-connector-javaMySQL Connector/J的完整名称,其中“J”表示Java,是指这是一个Java驱动程序。而mysql-connector-j则是mysql-connector-java的简写,两者是同一个东西,只是名称不同。 ### 回答2: mysql-connector-javamysql-connector-j都是用于连接Java应用程序和MySQL数据库的驱动程序。它们之间的主要区别可以从以下几个方面来看。 1. 命名方式:mysql-connector-java是根据JDBC(Java数据库连接)的命名方式来命名的,而mysql-connector-j是MySQL Connector/J的缩写命名方式。 2. 版本历史:mysql-connector-javaMySQL官方发布的Java驱动程序,它的版本号与MySQL数据库的版本号是对应的。而mysql-connector-j是在mysql-connector-java的基础上进行二次开发和维护的版本。 3. 社区贡献:mysql-connector-javaMySQL官方维护,更新频率较稳定,并提供了常见的功能和支持。而mysql-connector-j则是由独立的开发者或第三方贡献者维护,更新可能相对较少。 4. 功能支持:由于mysql-connector-javaMySQL官方的驱动程序,它相对完整地支持了MySQL数据库的各种功能,如事务处理、存储过程等。而mysql-connector-j则可能只支持部分数据库功能,具体取决于开发者对其进行的二次开发。 总体来说,mysql-connector-java是更常用和可靠的MySQL数据库驱动程序,由MySQL官方提供支持和维护。而mysql-connector-j则可能是由第三方进行了一些个性化的开发和定制,可能用于特定的应用场景。选择使用哪个驱动程序取决于具体的需求和项目要求。 ### 回答3: mysql-connector-javamysql-connector-j其实是指的同一个东西,都是用于Java程序连接MySQL数据库的驱动程序。mysql-connector-java是该驱动程序的官方名称,而mysql-connector-j则是该驱动程序的简称。 mysql-connector-javaJava语言开发的,它提供了一个API,使得Java程序可以直接连接和操作MySQL数据库。通过mysql-connector-javaJava程序可以执行数据的增删改查操作,执行SQL语句,以及连接和断开数据库等。 mysql-connector-j是mysql-connector-java的缩写形式,常用于命令行或脚本的写作。在一些场景中,为了方便输入或提高效率,人们更倾向于使用mysql-connector-j这个简称。 总结来说,mysql-connector-javamysql-connector-j在功能和使用上并没有实质的差别,只是一个是官方名称,一个是简称。无论是使用mysql-connector-java还是mysql-connector-j,都是为了实现Java程序与MySQL数据库的连接和操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值