如何在 Java 中点击控制器之前消除特殊字符?
How to eliminate special characters before hitting the controller in Java?
我有一个用例,我需要验证我的控制器的传入请求正文是否包含 Hybris 店面中的任何特殊字符。虽然可以通过屏蔽任何特殊字符从前端实现,但我们需要后端验证。
我尝试使用 HandlerIntercepterAdapter
拦截请求并验证任何特殊字符。但是每当我使用 request.getReader()
或 request.getInputStream()
并读取数据时,请求正文都会被清除。
我尝试使用 IOUtils.copy()
但这也从原始请求中读取并使正文为空。
即使在使用 HttpServletRequestWrapper
或 ContentCachingRequestWrapper
包装请求之后,请求正文也会被清除。我猜它在内部某处使用相同的参考。
我尝试关注 this thread 但无法解决此问题。
我正在寻找一种解决方案,我可以在其中提取请求正文并验证它而不让它被清除,以便它可以在不同的控制器中使用[或]任何有助于防止任何特殊字符命中的替代方法控制器。
any alternative approach which can help in preventing any special characters to hit the controller.
如果您尝试执行以下操作会怎样...
- 获取请求正文
- 处理它
- 通过将正文设置为已处理版本,在您的过滤器中再次设置请求正文?
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest originalRequest = (HttpServletRequest) request;
HttpServletResponse originalResponse = (HttpServletResponse) response;
/**
* 2.Read the original request body and change it
*/
String originalRequestBody = ServletUtil.readRequestBody(originalRequest); // Read the original request body
// Body is processed here !
String modifyRequestBody = processBody(originalRequestBody); // Modify request body (clear text)
HttpServletRequest orginalRequest = (HttpServletRequest) request;
ModifyRequestBodyWrapper requestWrapper = new ModifyRequestBodyWrapper(orginalRequest, modifyRequestBody);
/**
* 3. Build a new response object
*/
ModifyResponseBodyWrapper responseWrapper = new ModifyResponseBodyWrapper(originalResponse);
chain.doFilter(requestWrapper, responseWrapper);
String originalResponseBody = responseWrapper.getResponseBody(); // Original response body (clear text)
String modifyResponseBody = this.encryptBody(originalResponseBody); // Modified response volume (ciphertext)
/**
* 4.Output the modified response body with the output stream of the original response object
* To ensure that the response type is consistent with the original request, and reset the response body size
*/
originalResponse.setContentType(requestWrapper.getOrginalRequest().getContentType()); // Be consistent with the request
byte[] responseData = modifyResponseBody.getBytes(responseWrapper.getCharacterEncoding()); // The coding is consistent with the actual response
originalResponse.setContentLength(responseData.length);
@Cleanup ServletOutputStream out = originalResponse.getOutputStream();
out.write(responseData);
}
这里有一个代码示例,其中implements这个。
应在表单中设置输入。
在您的控制器中,您可以使用验证器:
@RequestMapping(value = "/process", method = RequestMethod.POST)
public String doValidateAndPost(final MyForm form, final BindingResult bindingResult,
final HttpServletRequest request, final Model model){
getMyValidator().validate(form, bindingResult);
if (bindingResult.hasErrors())
{
return MY_PAGE;
}
验证器将如下所示:
@Override
public void validate(final Object object, final Errors errors)
{
final MyForm form = (MyForm ) object;
final String data = form.getMyData();
Pattern p = Pattern.compile("[^a-z0-9 ]", Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(data );
boolean b = m.find();
if (b)
{
errors.rejectValue("myData", "myData.invalid");
}
}
您还可以使用 @Valid
注释:
public String doValidateAndPost(@Valid final MyForm form ...
并在您的表单中设置:
@Pattern(regexp = "[a-z0-9 ]")
private String myData;
我有一个用例,我需要验证我的控制器的传入请求正文是否包含 Hybris 店面中的任何特殊字符。虽然可以通过屏蔽任何特殊字符从前端实现,但我们需要后端验证。
我尝试使用 HandlerIntercepterAdapter
拦截请求并验证任何特殊字符。但是每当我使用 request.getReader()
或 request.getInputStream()
并读取数据时,请求正文都会被清除。
我尝试使用 IOUtils.copy()
但这也从原始请求中读取并使正文为空。
即使在使用 HttpServletRequestWrapper
或 ContentCachingRequestWrapper
包装请求之后,请求正文也会被清除。我猜它在内部某处使用相同的参考。
我尝试关注 this thread 但无法解决此问题。
我正在寻找一种解决方案,我可以在其中提取请求正文并验证它而不让它被清除,以便它可以在不同的控制器中使用[或]任何有助于防止任何特殊字符命中的替代方法控制器。
any alternative approach which can help in preventing any special characters to hit the controller.
如果您尝试执行以下操作会怎样...
- 获取请求正文
- 处理它
- 通过将正文设置为已处理版本,在您的过滤器中再次设置请求正文?
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest originalRequest = (HttpServletRequest) request;
HttpServletResponse originalResponse = (HttpServletResponse) response;
/**
* 2.Read the original request body and change it
*/
String originalRequestBody = ServletUtil.readRequestBody(originalRequest); // Read the original request body
// Body is processed here !
String modifyRequestBody = processBody(originalRequestBody); // Modify request body (clear text)
HttpServletRequest orginalRequest = (HttpServletRequest) request;
ModifyRequestBodyWrapper requestWrapper = new ModifyRequestBodyWrapper(orginalRequest, modifyRequestBody);
/**
* 3. Build a new response object
*/
ModifyResponseBodyWrapper responseWrapper = new ModifyResponseBodyWrapper(originalResponse);
chain.doFilter(requestWrapper, responseWrapper);
String originalResponseBody = responseWrapper.getResponseBody(); // Original response body (clear text)
String modifyResponseBody = this.encryptBody(originalResponseBody); // Modified response volume (ciphertext)
/**
* 4.Output the modified response body with the output stream of the original response object
* To ensure that the response type is consistent with the original request, and reset the response body size
*/
originalResponse.setContentType(requestWrapper.getOrginalRequest().getContentType()); // Be consistent with the request
byte[] responseData = modifyResponseBody.getBytes(responseWrapper.getCharacterEncoding()); // The coding is consistent with the actual response
originalResponse.setContentLength(responseData.length);
@Cleanup ServletOutputStream out = originalResponse.getOutputStream();
out.write(responseData);
}
这里有一个代码示例,其中implements这个。
应在表单中设置输入。
在您的控制器中,您可以使用验证器:
@RequestMapping(value = "/process", method = RequestMethod.POST)
public String doValidateAndPost(final MyForm form, final BindingResult bindingResult,
final HttpServletRequest request, final Model model){
getMyValidator().validate(form, bindingResult);
if (bindingResult.hasErrors())
{
return MY_PAGE;
}
验证器将如下所示:
@Override
public void validate(final Object object, final Errors errors)
{
final MyForm form = (MyForm ) object;
final String data = form.getMyData();
Pattern p = Pattern.compile("[^a-z0-9 ]", Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(data );
boolean b = m.find();
if (b)
{
errors.rejectValue("myData", "myData.invalid");
}
}
您还可以使用 @Valid
注释:
public String doValidateAndPost(@Valid final MyForm form ...
并在您的表单中设置:
@Pattern(regexp = "[a-z0-9 ]")
private String myData;