我有一个自定义的 spring AuthenticationProvider
类,但尝试在 loadUserDetails
方法中拦截 HTTPServletRequest
和 HTTPServletResponse
。
@Component("darnGoodAuthenticaionProvider")
public class DarnGoodAuthenticaionProvider
extends HandlerInterceptorAdapter
implements AuthenticationUserDetailsService {
private HttpServletRequest request;
private HttpServletResponse response;
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler)
throws Exception {
this.request = request;
this.response = response;
// we don't want anything falling here
return true;
}
@Override
public UserDetails loadUserDetails(Authentication token)throws
UsernameNotFoundException{
.......
}
}
我知道 HandlerIntercepterAdapter
中的 preHandler
方法能够完成这项工作,但我如何确定 preHandler
方法在 loadUserDetails
之前被调用,以便我可以准备好请求和响应?
谢谢
最佳答案
在 servlet 容器上,每个请求将从收到请求的那一刻开始处理,直到仅由一个线程返回响应(请求 == 当前线程)。
因此,问题是在 Spring Security 过滤器链之前放置一个 Servlet 过滤器(过滤器映射元素位于 Spring Security 的过滤器映射之上),并使用 ThreadLocal 变量将请求和响应存储在线程中 - 另请参阅此 answer .
然后在 DarnGoodAuthenticaionProvider
上使用静态方法 RequestResponseHolder.getRequest()
访问请求。
web.xml 配置:
<filter>
<filter-name>saveRequestResponseFilter</filter-name>
<filter-class>sample.save.request.filter.SaveRequestResponseFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>saveRequestResponseFilter</filter-name>
<url-pattern>/mobilews/*</url-pattern>
</filter-mapping>
过滤以在线程中保存请求响应:
public class SaveRequestResponseFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
RequestResponseHolder.setRequestResponse(req,resp);
try {
chain.doFilter(request, response);
}
finally {
RequestResponseHolder.clear();
}
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
...
}
@Override
public void destroy() {
...
}
}
请求/响应持有者:
public class RequestResponseHolder {
private static ThreadLocal<HttpServletRequest> requestHolder = new ThreadLocal<HttpServletRequest>();
private static ThreadLocal<HttpServletResponse> responseHolder = new ThreadLocal<HttpServletResponse>();
public static void setRequestResponse(HttpServletRequest request, HttpServletResponse response) {
requestHolder.set(request);
responseHolder.set(response);
}
public static HttpServletRequest getServletRequest(){
return requestHolder.get();
}
public static HttpServletResponse getServletResponse() {
return responseHolder.get();
}
public static void clear() {
requestHolder.remove();
responseHolder.remove();
}
}
从 DarnGoodAuthenticaionProvider
获取请求:
HttpServletRequest req = RequestResponseHolder.getServletRequest();
关于java - 在 loadUserDetails 方法中捕获 httpServeletRequest,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21123852/