I am using a HMAC Authentication filter. In the filter when I access my POST Request Body, I am able to get the XML in it. When I try to access the XML in the controller I am get a blank string. The xmlString
in the filter is giving the proper XML but the xmlString
in the controller is giving blank string. I am using Spring MVC.
我正在使用HMAC身份验证过滤器。在我访问POST Request Body的过滤器中,我能够获取XML。当我尝试访问控制器中的XML时,我得到一个空白字符串。过滤器中的xmlString提供了正确的XML,但控制器中的xmlString给出了空字符串。我正在使用Spring MVC。
My filter is:
我的过滤器是:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String authorisation = httpRequest.getHeader("authorization");
String accessKeyId = authorisation.split(":")[0].split(" ")[1];
String signature = authorisation.split(":")[1];
String secretAccessKey = getSecretAccessKey(accessKeyId);
InputStream xmlStream = httpRequest.getInputStream();
String xmlString = IOUtils.toString(xmlStream, "UTF-8");
String encodedXml = new String();
try {
encodedXml = HMACEncoder.calculateHMAC(xmlString, secretAccessKey);
} catch (SignatureException e) {
e.printStackTrace();
}
if (!signature.equals(encodedXml))
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
else
chain.doFilter(request, response);
}
and my controller is:
我的控制器是:
@RequestMapping(value = "/user", method = RequestMethod.POST)
public String fetchUserString(HttpServletRequest request) {
InputStream xml = null;
String xmlString = null;
try {
xml = request.getInputStream();
xmlString = IOUtils.toString(xml, "UTF-8");
} catch (IOException e) {
e.printStackTrace();
}
return xmlString;
}
2 个解决方案
#1
You can't read the stream twice, comment the code in filter and read only in controller.
您无法读取流两次,在过滤器中注释代码并仅在控制器中读取。
#2
As praki suggested, I put the XML in a request attribute and in my controller I got it from the request attribute and then put the XML in a ModelAttribute
. Here is my code:
正如praki建议的那样,我将XML放在请求属性中,在我的控制器中,我从请求属性中获取它,然后将XML放在ModelAttribute中。这是我的代码:
My filter:
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
if (httpRequest.getMethod().equalsIgnoreCase("POST")) {
String authorisation = httpRequest.getHeader("authorization");
String accessKeyId = authorisation.split(":")[0].split(" ")[1];
String signature = authorisation.split(":")[1];
String secretAccessKey = getSecretAccessKey(accessKeyId);
ServletInputStream servletStream = httpRequest.getInputStream();
String xmlString = IOUtils.toString(servletStream);
String encodedXml = new String();
try {
encodedXml = HMACEncoder.calculateHMAC(xmlString, secretAccessKey);
} catch (SignatureException e) {
e.printStackTrace();
}
httpRequest.setAttribute("content", xmlString);
if (!signature.equals(encodedXml))
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
else
chain.doFilter(request, response);
} else
chain.doFilter(request, response);
}
and my controller:
和我的控制器:
@RequestMapping(value = "/add", method = RequestMethod.POST, produces = "application/xml")
public @ResponseBody Catalog addCatalog(@ModelAttribute("catalog") Catalog catalog) {
logger.info("In addCatalog with " + catalog);
catalog.getHeader().setOrganizationId(IConstant.ORGANIZATION_ID_BSL);
try {
catalog = catalogService.addCatalogIntegration(catalog);
} catch (Exception e) {
e.printStackTrace();
}
logger.info("Returning from addCatalog with " + catalog);
return catalog;
}
@ModelAttribute("catalog")
private Catalog getCatalog(HttpServletRequest request) throws Exception {
Catalog catalog = new Catalog();
try {
String xml = (String) request.getAttribute("content");
if (xml != null) {
JAXBContext jaxbContext = JAXBContext.newInstance(Catalog.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
catalog = (Catalog) unmarshaller.unmarshal(new StringReader(xml));
}
} catch (Exception e) {
e.printStackTrace();
}
return catalog;
}
#1
You can't read the stream twice, comment the code in filter and read only in controller.
您无法读取流两次,在过滤器中注释代码并仅在控制器中读取。
#2
As praki suggested, I put the XML in a request attribute and in my controller I got it from the request attribute and then put the XML in a ModelAttribute
. Here is my code:
正如praki建议的那样,我将XML放在请求属性中,在我的控制器中,我从请求属性中获取它,然后将XML放在ModelAttribute中。这是我的代码:
My filter:
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
if (httpRequest.getMethod().equalsIgnoreCase("POST")) {
String authorisation = httpRequest.getHeader("authorization");
String accessKeyId = authorisation.split(":")[0].split(" ")[1];
String signature = authorisation.split(":")[1];
String secretAccessKey = getSecretAccessKey(accessKeyId);
ServletInputStream servletStream = httpRequest.getInputStream();
String xmlString = IOUtils.toString(servletStream);
String encodedXml = new String();
try {
encodedXml = HMACEncoder.calculateHMAC(xmlString, secretAccessKey);
} catch (SignatureException e) {
e.printStackTrace();
}
httpRequest.setAttribute("content", xmlString);
if (!signature.equals(encodedXml))
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
else
chain.doFilter(request, response);
} else
chain.doFilter(request, response);
}
and my controller:
和我的控制器:
@RequestMapping(value = "/add", method = RequestMethod.POST, produces = "application/xml")
public @ResponseBody Catalog addCatalog(@ModelAttribute("catalog") Catalog catalog) {
logger.info("In addCatalog with " + catalog);
catalog.getHeader().setOrganizationId(IConstant.ORGANIZATION_ID_BSL);
try {
catalog = catalogService.addCatalogIntegration(catalog);
} catch (Exception e) {
e.printStackTrace();
}
logger.info("Returning from addCatalog with " + catalog);
return catalog;
}
@ModelAttribute("catalog")
private Catalog getCatalog(HttpServletRequest request) throws Exception {
Catalog catalog = new Catalog();
try {
String xml = (String) request.getAttribute("content");
if (xml != null) {
JAXBContext jaxbContext = JAXBContext.newInstance(Catalog.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
catalog = (Catalog) unmarshaller.unmarshal(new StringReader(xml));
}
} catch (Exception e) {
e.printStackTrace();
}
return catalog;
}