SpringSecurity登录报错403问题:com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field异常、及 Jackson 的使用
项目使用SpringSecurity进行安全管理,之前登录接口都是好好的,今天突然验证码登录一直报403,最后发现问题所在,记录一下。
一、问题背景与解决方案
因为前端登录注册使用差不多相同的流程,所以使用了 mixins ,表单对象如下:
loginForm: {
phoneNum: '',
password: '',
repeatPassword: '', // 最早是没有这个字段的,因为做忘记密码,所以也采用了这个mixin,然后加了这个字段
code: ''
},
问题就出在加的那个字段上,后台SpringSecurity的拦截器上获取请求参数采用的这个方法
// 登录是否含手机号
User voUser = new ObjectMapper().readValue(req.getInputStream(), User.class);
if (voUser == null || voUser.getPhoneNum() == null) {
throw new AuthenticationServiceException("请输入手机号");
}
而我的 User.class 之前没做忘记密码之前,实体类也没加这个字段
private String repeatPassword;
所以导致匹配不上这个类,所以报错:com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "repeatPassword"
解决方案就是:将 repeatPassword 这个字段在实体类上加上即可。
但是肯定不能这么简单就了事,本着遇到问题就学习的精神,所以把这个 new ObjectMapper().readValue() 这个东西研究一下先。
二、Jackson 介绍
new ObjectMapper().readValue() 这个东西来源于 jackson。
1、jackson是什么
Java下常见的Json类库有Gson、JSON-lib和Jackson等,Jackson相对来说比较高效,在项目中主要使用Jackson进行JSON和Java对象转换,下面给出一些Jackson的JSON操作方法。
2、准备工作
首先去官网下载Jackson工具包,下载地址http://wiki.fasterxml.com/JacksonDownload。Jackson有1.x系列和2.x系列,2.x系列有3个jar包需要下载:
jackson-core-2.2.3.jar
jackson-annotations-2.2.3.jar
jackson-databind-2.2.3.jar
但是如果使用SpringBoot就很方便啦,不需要这步,因为springboot默认配置的 json 转换工具就是 jackson。
3、JSON序列化 —— JAVA对象转JSON
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonDemo {
public static void main(String[] args) throws ParseException, IOException {
User user = new User();
user.setName("小民");
user.setEmail("xiaomin@sina.com");
user.setAge(20);
SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd");
user.setBirthday(dateformat.parse("1996-10-01"));
/**
* ObjectMapper是JSON操作的核心,Jackson的所有JSON操作都是在ObjectMapper中实现。
* ObjectMapper有多个JSON序列化的方法,可以把JSON字符串保存File、OutputStream等不同的介质中。
* writeValue(File arg0, Object arg1)把arg1转成json序列,并保存到arg0文件中。
* writeValue(OutputStream arg0, Object arg1)把arg1转成json序列,并保存到arg0输出流中。
* writeValueAsBytes(Object arg0)把arg0转成json序列,并把结果输出成字节数组。
* writeValueAsString(Object arg0)把arg0转成json序列,并把结果输出成字符串。
*/
ObjectMapper mapper = new ObjectMapper();
//User类转JSON
//输出结果:{"name":"小民","age":20,"birthday":844099200000,"email":"xiaomin@sina.com"}
String json = mapper.writeValueAsString(user);
System.out.println(json);
//Java集合转JSON
//输出结果:[{"name":"小民","age":20,"birthday":844099200000,"email":"xiaomin@sina.com"}]
List<User> users = new ArrayList<User>();
users.add(user);
String jsonlist = mapper.writeValueAsString(users);
System.out.println(jsonlist);
}
}
ObjectMapper是JSON操作的核心,Jackson的所有JSON操作都是在ObjectMapper中实现。
ObjectMapper有多个JSON序列化的方法,可以把JSON字符串保存File、OutputStream等不同的介质中。
(1)writeValue(File arg0, Object arg1)把arg1转成json序列,并保存到arg0文件中。
(2)writeValue(OutputStream arg0, Object arg1)把arg1转成json序列,并保存到arg0输出流中。
(3)writeValueAsBytes(Object arg0)把arg0转成json序列,并把结果输出成字节数组。
(4)writeValueAsString(Object arg0)把arg0转成json序列,并把结果输出成字符串。
4、JSON反序列化 —— JSON转Java类
import java.io.IOException;
import java.text.ParseException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonDemo {
public static void main(String[] args) throws ParseException, IOException {
String json = "{\"name\":\"小民\",\"age\":20,\"birthday\":844099200000,\"email\":\"xiaomin@sina.com\"}";
/**
* ObjectMapper支持从byte[]、File、InputStream、字符串等数据的JSON反序列化。
*/
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(json, User.class);
System.out.println(user);
}
}
ObjectMapper支持从byte[]、File、InputStream、字符串等数据的JSON反序列化。主要采用的就是 readValue() 方法。
5、Jackson 注解
Jackson提供了一系列注解,方便对JSON序列化和反序列化进行控制,下面介绍一些常用的注解。
@JsonIgnore 此注解用于属性上,作用是进行JSON操作时忽略该属性。
@JsonFormat 此注解用于属性上,作用是把Date类型直接转化为想要的格式,如@JsonFormat(pattern = "yyyy-MM-dd HH-mm-ss")。
@JsonProperty 此注解用于属性上,作用是把该属性的名称序列化为另外一个名称,如把trueName属性序列化为name,@JsonProperty("name")。
// 比如我们常用的时间格式化注解,就是这个 jackson 里的啦
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8")
private Date createTime;
// 不JSON序列化年龄属性
@JsonIgnore
private Integer age;
// 序列化email属性为mail
@JsonProperty("mail")
private String email;
6、自定义配置文件
#jackson
#日期格式化
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
#spring.jackson.date-format=yyyy-MM-dd
#格式化输出
spring.jackson.serialization.indent_output=true
#忽略无法转换的对象
spring.jackson.serialization.fail_on_empty_beans=false
#设置空如何序列化
spring.jackson.defaultPropertyInclusion=NON_EMPTY
#允许对象忽略json中不存在的属性
spring.jackson.deserialization.fail_on_unknown_properties=false
#允许出现特殊字符和转义符
spring.jackson.parser.allow_unquoted_control_chars=true
#允许出现单引号
spring.jackson.parser.allow_single_quotes=true
加了这个配置,spring.jackson.date-format=yyyy-MM-dd HH:mm:ss,我们就不需要再在实体类里去加这样的注解了。
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8")
private Date createTime;
注意时区是必须要加的,上面配置没有加时区
#jackson相关配置
spring.jackson.date-format = yyyy-MM-dd HH:mm:ss
#时区必须要设置
spring.jackson.time-zone= GMT+8
#ALWAYS的意思是即时属性为null,仍然也会输出这个key
spring.jackson.default-property-inclusion=ALWAYS
yml形式
spring:
jackson:
#参数意义:
#JsonInclude.Include.ALWAYS 默认
#JsonInclude.Include.NON_DEFAULT 属性为默认值不序列化
#JsonInclude.Include.NON_EMPTY 属性为 空(””) 或者为 NULL 都不序列化
#JsonInclude.Include.NON_NULL 属性为NULL 不序列化
default-property-inclusion: ALWAYS
time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss
7、创建bean、及在配置类中修改属性,可以看这篇博客:https://blog.csdn.net/weixin_38413579/article/details/82562634
三、继续解决方案
然后我们继续看问题的解决方案。
1、第一种解决方案
ObjectMapper 对象添加:mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
String s = "{\"id\":1,\"name\":\"test\",\"age\":19}";
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
User value = mapper.readValue(s, User.class);
System.out.println(value);
2、第二种解决方案
在需要转化的对象的类中添加注解,注解信息如下
@JsonIgnoreProperties(ignoreUnknown = true)
public class User{
......
}
3、第三种解决方案,就是上面的在实体类上加上对应的字段
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
2017-06-23 iframe多层嵌套时获取元素