多次使用HttpServletRequest和方法之间的链

时间:2017-06-23 07:16:39

标签: java spring servlets

我必须多次阅读HttpServletRequest。我已经像在Http Servlet request lose params from POST body after read it once

这些帖子中所说的那样包装了HttpServletRequest

在我的扩展AbstractAuthenticationProcessingFilter的过滤器类中,我可以在successAuthentication方法中使用和链接请求,因为它有链参数。但除了那些解决方案之外,我还必须在尝试和成功的身份验证步骤之间链接请求:

public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException {
            // wrapping request and consuming
        }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        // Since i couldn't chain wrapped httpServletRequest from attemptAuthentication step, this request still gets non-wrapping one and  inputstream is empty
    }

如何将包装请求从attemptAuthentication传递给successfulAuthentication?

2 个答案:

答案 0 :(得分:0)

没有这样的方法。你可以做的唯一事情是每次你要在一个过滤器中读取它时包装请求。每次在阅读复制正文之前请将请求换行。

查看包装器的一些工作代码,例如here

答案 1 :(得分:0)

这是一个古老的问题,但是如果有人遇到相同的问题:

您可以像上一个答案中所建议的那样包装请求,但是需要先包装它,然后再通过身份验证过滤器对其进行过滤:

Spring安全配置将如下所示:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        AuthFilter authFilter = new AuthFilter();
        WrapperFilter wrapperFilter = new WrapperFilter();
        http    .cors()
                .and()
                .csrf().disable()
                .exceptionHandling().authenticationEntryPoint(exceptionHandler)
                .and()
                .authorizeRequests()
                .antMatchers("/v1/*", "/api/*")
                .authenticated()
                .and()
                .addFilterBefore(authFilter, BasicAuthenticationFilter.class)
                .addFilterBefore(wrapperFilter, AuthFilter.class);
    }

因此包装过滤器先于您的auth过滤器和包装过滤器的doFilter包装请求并将其传递:

@Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        MultiReadHttpServletRequest wrapper = new MultiReadHttpServletRequest((HttpServletRequest) request);
        chain.doFilter(wrapper, response);
    }

MultiReadHttpServletRequest如下:

public class MultiReadHttpServletRequest extends HttpServletRequestWrapper {

    private byte[] body;

    public MultiReadHttpServletRequest(HttpServletRequest request) {
        super(request);
        try {
            body = IOUtils.toByteArray(request.getInputStream());
        } catch (IOException ex) {
            body = new byte[0];
        }
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream(), getCharacterEncoding()));
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        return new ServletInputStream() {
            ByteArrayInputStream wrapperStream = new ByteArrayInputStream(body);

            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }

            @Override
            public int read() throws IOException {
                return wrapperStream.read();
            }
        };
    }
}