Mat*_*son 9 java security rest spring spring-boot
我正在使用具有云功能的收据打印机。它与我正在实施的服务器规范相通讯。它每x秒用POST请求轮询URL,并且POST响应中包含某条信息时,打印机将GET请求发送到该URL,以获取要打印的信息。
我将打印服务器实现为Spring Boot服务器,而POST方法遇到一些奇怪的问题,我需要一些帮助。
我的问题是从打印机到服务器的POST请求从不发送到控制器。但是,我能够将Postman的POST请求发送到完全相同的URL,并由控制器处理。
该URL就是:https:// www。[my-domain] .com:[port-number] / cloudprint
另外,我尝试将控制器方法复制到另一个在Apache后面的Tomcat实例上运行的Spring(不是Boot)应用程序中,并且打印机的POST请求由控制器方法处理。我可以在Apache日志和Tomcat日志中看到它们。当前的轮询频率为10秒。
控制器的外观如下:
package com.[my-domain].[application-name].controller;
[a bunch of imports]
@RestController
@CrossOrigin
public class PrintController {
Logger logger = LoggerFactory.getLogger(PrintController.class);
@RequestMapping(value="/cloudprint", method=RequestMethod.POST,
headers={"Accept=application/json"})
@ResponseStatus(HttpStatus.CREATED)
public @ResponseBody String printPost() {
logger.debug("in printPost");
return "OK";
}
@RequestMapping(value="/cloudprint", method=RequestMethod.GET,
headers={"Accept=application/json"})
@ResponseStatus(HttpStatus.OK)
public @ResponseBody String printGet(HttpServletRequest request) {
logger.debug("in printGet");
return "OK";
}
@RequestMapping(value="/cloudprint", method=RequestMethod.DELETE,
headers={"Accept=application/json"})
@ResponseStatus(HttpStatus.OK)
public @ResponseBody String printDelete() {
logger.debug("in printDelete");
return "OK";
}
}
Run Code Online (Sandbox Code Playgroud)
是什么原因造成的?我可以测试什么来解决此问题?
---添加的信息低于2019-06-03 @ 13:21 cet ---由于我有一个常规的Spring(non-boot)应用程序,可以接受来自打印机的POST请求,因此我可以将信息记录在接收到的信息中请求。所以我做到了。
这是来自打印机的POST请求之一,Spring boot oontroller不接受:
auth type: null
content type: application/json
-- HEADERS --
Header: host : dev.[our-domain-name].com
Header: accept : */*
Header: user-agent : Cente HTTPc
Header: content-type : application/json
Header: content-length : 303
Header: connection : keep-alive
QueryString: null
-- PARAMETERS --
END
Run Code Online (Sandbox Code Playgroud)
这是邮递员对完全相同的URL的POST请求之一,Spring启动oontroller接受该请求:
auth type: null
cotent type: application/json
-- HEADERS --
Header: content-type : application/json
Header: cache-control : no-cache
Header: Postman-Token : caf99fa1-4730-4193-aab3-c4874273661d
Header: user-agent : PostmanRuntime/7.6.0
Header: accept : */*
Header: host : dev.[our-domain-name].com
Header: accept-encoding : gzip, deflate
Header: content-length : 0
Header: connection : keep-alive
QueryString: null
-- PARAMETERS --
END
Run Code Online (Sandbox Code Playgroud)
分析:1.用户代理标头不同。2.内容长度标头不同。3.邮递员请求具有来自云打印机的请求所没有的三个标头。它们是:缓存控制,Postman令牌和接受编码
---添加的信息如下2019-06-03 @ 17:56 cet ---好吧,我想出了如何记录消息正文。这是一个格式正确的json结构,确实包含303个字符:
{"status": "29 a 0 0 0 0 0 0 0 0 0 0",
"printerMAC": "00:11:62:1b:xx:xx",
"statusCode": "200%20OK",
"printingInProgress": false,
"clientAction": null,
"display": [
{"name": "MainDisplay" ,
"status": {"connected": false}}],
"barcodeReader": [
{"name": "MainBCR" ,
"status": {"connected": false,"claimed": false}}]}
Run Code Online (Sandbox Code Playgroud)
我创建了相应的类,并将Boot应用程序中的POST方法更改为:
@RequestMapping(value="/cloudprint", method=RequestMethod.POST,
headers={"Accept=application/json"})
@ResponseStatus(HttpStatus.CREATED)
public @ResponseBody String printPost(@RequestBody PrinterPostRequest printerPostRequest,
HttpServletRequest request) {
HttpRequestLogger.log(request);
return "OK";
}
Run Code Online (Sandbox Code Playgroud)
尽管如此,它仍未从打印机接收POST请求。它拾取Postman请求并将请求正文json成功编组到类中。
---添加的信息如下2019-06-05 @ 10:16等等---我有个主意。使用Spring RestTemplate,我以与打印机发送的请求相同的标题和有效负载向boot应用程序发送了POST请求。我收到带有以下消息的org.springframework.web.client.ResourceAccessException:
I/O error on POST request for "https://boot.[my-domain].com:8443/cloudprint":sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Run Code Online (Sandbox Code Playgroud)
If you use Spring Boot 2, then it could happen because of the csrf-protection. It affects only the non-GET requests, and it's turned on by default on Spring Boot 2, but it's off in earlier versions.
So it quite well reflects your issue-description - although I don't fully understand how could it work via Postman... however there is a chance that it handles it automatically somehow...
Anyway it could worth a try:
@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
}
}
Run Code Online (Sandbox Code Playgroud)