如何在 Java 中点击控制器之前消除特殊字符?

How to eliminate special characters before hitting the controller in Java?

我有一个用例,我需要验证我的控制器的传入请求正文是否包含 Hybris 店面中的任何特殊字符。虽然可以通过屏蔽任何特殊字符从前端实现,但我们需要后端验证。

我尝试使用 HandlerIntercepterAdapter 拦截请求并验证任何特殊字符。但是每当我使用 request.getReader()request.getInputStream() 并读取数据时,请求正文都会被清除。 我尝试使用 IOUtils.copy() 但这也从原始请求中读取并使正文为空。 即使在使用 HttpServletRequestWrapperContentCachingRequestWrapper 包装请求之后,请求正文也会被清除。我猜它在内部某处使用相同的参考。 我尝试关注 this thread 但无法解决此问题。

我正在寻找一种解决方案,我可以在其中提取请求正文并验证它而不让它被清除,以便它可以在不同的控制器中使用[或]任何有助于防止任何特殊字符命中的替代方法控制器。

any alternative approach which can help in preventing any special characters to hit the controller.

如果您尝试执行以下操作会怎样...

  1. 获取请求正文
  2. 处理它
  3. 通过将正文设置为已处理版本,在您的过滤器中再次设置请求正文?
@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;