我试图在我的Web服务中反序列化发布请求,但最终得到HTTP 500提示javax.json.bind.JsonbException: Error deserialize JSON value into type: class [C
。我正在使用Jackson来处理JSON内容。
这是我从邮递员发送的JSON字符串:
{"firstName":"FirstName","middleName":"middleName","lastName":"LastName","name":"SomeName","password":"$0meR@nd0m","creationTimeStamp":1533950475466}
这是我的POJO:
@XmlRootElement
public class UserFormInterceptor {
@Pattern(regexp = "^[\\S][\\p{L} .'-]+$") @Size(min = 2, max = 64) @NotEmpty @NotNull
private String firstName;
@Pattern(regexp = "^[\\S][\\p{L} .'-]+$") @Size(min = 2, max = 64)
private String middleName;
@Pattern(regexp = "^[\\S][\\p{L} .'-]+$") @Size(min = 2, max = 64) @NotEmpty @NotNull
private String lastName;
@Pattern(regexp = "^[a-zA-z][\\w]*$") @Size(min = 8, max = 64) @NotEmpty @NotNull
private String name;
@Pattern(regexp = "(?=.*?[A-Z]+)(?=.*?[0-9]+)(?=.*?[\\p{Punct}]+).*") @Size(min = 8, max = 64) @NotEmpty @NotNull
private char[] password;
@Positive @NotEmpty @NotNull
private long creationTimeStamp;
public UserFormInterceptor() {}
public UserFormInterceptor(@NotNull String name, @NotNull String password, @Positive long creationTimeStamp, @NotNull String firstName, String middleName, @NotNull String lastName) {
this.name = name;
this.password = password.toCharArray();
this.creationTimeStamp = creationTimeStamp;
this.firstName = firstName;
this.middleName = middleName;
this.lastName = lastName;
}
@NotNull
public String getFirstName() {
return firstName;
}
public void setFirstName(@NotNull String firstName) {
this.firstName = firstName;
}
public String getMiddleName() {
return middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
@NotNull
public String getLastName() {
return lastName;
}
public void setLastName(@NotNull String lastName) {
this.lastName = lastName;
}
@NotNull
public String getName() {
return name;
}
public void setName(@NotNull String name) {
this.name = name;
}
@NotNull
public char[] getPassword() {
return password;
}
public void setPassword(@NotNull String password) {
this.password = password.toCharArray();
}
public long getCreationTimeStamp() {
return creationTimeStamp;
}
public void setCreationTimeStamp(long creationTimeStamp) {
this.creationTimeStamp = creationTimeStamp;
}
public Map<String, Object> buildMap() {
Map<String,Object> returnMap = new HashMap<>();
returnMap.put("name",this.getName());
returnMap.put("firstName",this.firstName);
returnMap.put("middleName",this.middleName==null ? "" : this.middleName);
returnMap.put("lastName",this.lastName);
returnMap.put("creationTimeStamp",Long.toString(this.getCreationTimeStamp()));
return returnMap;
}
}
这是我的请求处理程序类:
@Path("/users")
public class UserController {
private static final UserDAO userDao = new UserDAO();
@POST
@Path(value = "/signup")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(value = MediaType.APPLICATION_JSON)
public Response signUpUser(@Valid @NotNull UserFormInterceptor userSignUpForm) {
UserCreatorModel userCreatorModel = (UserCreatorModel) new UserCreatorModel(userSignUpForm)
.setUniqueId();
String response = userDao.addCustomer(userCreatorModel);
return Response.ok(response).build();
}
}
这些是我对Jackson的Maven依赖:
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.jaxrs/jackson-jaxrs-json-provider -->
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.9.6</version>
</dependency>
这是堆栈跟踪:
StandardWrapperValve[Controller Servlet]: Servlet.service() for servlet Controller Servlet threw exception
javax.json.bind.JsonbException: Error deserialize JSON value into type: class [C.
at org.eclipse.yasson.internal.serializer.DeserializerBuilder.build(DeserializerBuilder.java:113)
at org.eclipse.yasson.internal.serializer.ObjectDeserializer.deserializeNext(ObjectDeserializer.java:161)
at org.eclipse.yasson.internal.serializer.AbstractContainerDeserializer.deserializeInternal(AbstractContainerDeserializer.java:84)
at org.eclipse.yasson.internal.serializer.AbstractContainerDeserializer.deserialize(AbstractContainerDeserializer.java:60)
at org.eclipse.yasson.internal.Unmarshaller.deserializeItem(Unmarshaller.java:57)
at org.eclipse.yasson.internal.Unmarshaller.deserialize(Unmarshaller.java:50)
at org.eclipse.yasson.internal.JsonBinding.deserialize(JsonBinding.java:45)
at org.eclipse.yasson.internal.JsonBinding.fromJson(JsonBinding.java:85)
at org.glassfish.jersey.jsonb.internal.JsonBindingProvider.readFrom(JsonBindingProvider.java:99)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.invokeReadFrom(ReaderInterceptorExecutor.java:257)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:236)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:156)
at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundReadFrom(MappableExceptionWrapperInterceptor.java:73)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:156)
at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1091)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:874)
at org.glassfish.jersey.server.ContainerRequest.readEntity(ContainerRequest.java:271)
at org.glassfish.jersey.server.internal.inject.EntityParamValueParamProvider$EntityValueSupplier.apply(EntityParamValueParamProvider.java:97)
at org.glassfish.jersey.server.internal.inject.EntityParamValueParamProvider$EntityValueSupplier.apply(EntityParamValueParamProvider.java:80)
at org.glassfish.jersey.server.spi.internal.ParamValueFactoryWithSource.apply(ParamValueFactoryWithSource.java:74)
at org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:92)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$AbstractMethodParamInvoker.getParamValues(JavaResourceMethodDispatcherProvider.java:133)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:200)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:103)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:493)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:415)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:104)
at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:277)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:272)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:268)
at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
at org.glassfish.jersey.internal.Errors.process(Errors.java:268)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:289)
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:256)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:703)
at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:416)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:370)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:389)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:342)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:229)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1580)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:258)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:652)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:591)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:371)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:238)
at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:463)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:168)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:242)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:539)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:593)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:573)
at java.lang.Thread.run(Thread.java:748)
]]
我也将Jackson依赖项的jar添加到了应用服务器的lib目录中。 我正在使用GlassFish 5.0和Jersey 2.26。 我做错了什么?该如何解决?
答案 0 :(得分:3)
提示在错误消息中:
Error deserialize JSON value into type: class [C
类[C
是对应于char[]
的类。
查看您的代码,您将password
声明为:
private char[] password;
将其更改为
private String password;
这是怎么回事,杰克逊不知道如何将JSON字符串反序列化为char[]
。
有种流派说您不应该使用Java字符串来保存密码...因为它据说可以使黑客从JVM内核中的非GC字符串中提取密码。倾倒。但是现实是,如果黑客能够以这种方式提取密码,那么他们很可能可以做其他事情来获取密码。此外,相同的密码极有可能在Glassfish框架类和/或JSON反序列化器内部创建的String
对象中。在这种情况下,使用char[]
最有可能是徒劳的。即使您解决了这些问题,只有尽快覆盖char[]
的内容,使用char[]
表示密码才更加安全。如果让char[]
在仍然保留密码的情况下无法访问,您将回到String
问题。