我必须多次阅读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?
答案 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();
}
};
}
}