处理来自Apache Tomcat servlet中同一客户端的重复GET请求的最佳策略是什么?
基本上,我得到的是两个请求相隔几秒钟,第一个来自客户端的真实IP,第二个来自TrendMicro服务器(这看起来与描述here的效果相同。 / p>
现在我的servlet忠实地为这两个请求提供服务但稍后会产生问题(因为它调用另一个很可能无法处理这种情况的远程服务)。
所以问题是,如何阻止第二个请求?或者还有其他策略可以解决这个问题吗?
谢谢!
答案 0 :(得分:2)
所以我刚刚发现这也导致我的网站出现问题。我存储了客户端在会话中请求的当前信息,但我收到的报告似乎是随机情况,用户将查看一个客户信息,查看其他客户信息,添加评论,但评论结束在第一个客户记录。
我今天找到了罪魁祸首。它是TrendMicro,镜像对查看第二个客户信息的真实用户和添加评论之间的第一个客户记录的调用。他们还欺骗cookie,这是主要问题。
IE中。 1)真实IP呼叫客户1信息(信息存储在会话中)
2)真实IP呼叫客户2信息(信息存储在会话中,替换客户1信息)
3)TrendMicro IP呼叫客户1信息(信息存储在会话中,替换客户2信息)
4)Real IP添加了评论,该评论被添加到会话中存储的客户,由于TrendMicro,现在是客户1。
解决方案? - 我添加了一项检查,以确保我们只为来自登录的IP地址的呼叫提供服务。
要做到这一点,你需要做两件事。
1)在您的登录代码上,在您验证登录凭据后,使用以下代码将用户IP地址存储在会话中:
session.setAttribute("LoginIPAddress", request.getRemoteAddr());
接下来,编写一个实现javax.servlet.Filter接口的类。
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpSession;
public class ServletUserAuthenticationFilter implements Filter {
// ----------------------------------------------------- Instance Variables
/**
* The default character forwardTo to set for requests that pass through
* this filter.
*/
protected String forwardTo = null;
/**
* Take this filter out of service.
*/
public void destroy() {
this.forwardTo = null;
}
/**
* Select and set (if specified) the character forwardTo to be used to
* interpret request parameters for this request.
*
* @param request The servlet request we are processing
* @param result The servlet response we are creating
* @param chain The filter chain we are processing
*
* @exception IOException if an input/output error occurs
* @exception ServletException if a servlet error occurs
*/
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
javax.servlet.http.HttpServletRequest httpRequest = (javax.servlet.http.HttpServletRequest)request;
HttpSession session = httpRequest.getSession();
// Is there a valid session?
// We now also redirect requests if the remote IP Address is not the same address that originally signed in
if(!httpRequest.getRequestURI().equals(httpRequest.getContextPath()+"/services/login") && !httpRequest.getRequestURI().equals(httpRequest.getContextPath()+"/services/logout")
&& (((session==null || session.getAttribute("userData")==null))
|| (session!=null && session.getAttribute("LoginIPAddress")!=null && !session.getAttribute("LoginIPAddress").equals(httpRequest.getRemoteAddr())))){
// An Https page has been requested, but no valid session has been found, ao forward the user to the page indicated by forwardTo
javax.servlet.http.HttpServletResponse httpResponse = (javax.servlet.http.HttpServletResponse)response;
StringBuffer logonQuery = new StringBuffer();
logonQuery.append(httpRequest.getScheme());
logonQuery.append("://");
logonQuery.append(request.getServerName());
logonQuery.append(":");
logonQuery.append(httpRequest.getLocalPort());
logonQuery.append(httpRequest.getContextPath());
logonQuery.append(forwardTo);
session = httpRequest.getSession(true);
session.setAttribute("MESSAGE", "Your session has expired. Please login again");
httpResponse.sendRedirect(logonQuery.toString());
return;
}
// Pass control on to the next filter
chain.doFilter(request, response);
}
/**
* Place this filter into service.
*
* @param filterConfig The filter configuration object
*/
public void init(FilterConfig filterConfig) throws ServletException {
this.forwardTo = filterConfig.getInitParameter("forwardTo");
}
}
我在这段代码中有一些您可能不需要的额外检查,但主要部分检查是!session.getAttribute(“LoginIPAddress”)。equals(httpRequest.getRemoteAddr())
最后,您需要在服务器每次收到请求时运行此代码,方法是将其添加到您的web.xml
<filter>
<filter-name>Check User Has Logged In</filter-name>
<filter-class>au.com.mySystem.utils.filter.ServletUserAuthenticationFilter</filter-class>
<init-param>
<param-name>forwardTo</param-name>
<param-value>/pages/loginForwarder.jsp</param-value>
</init-param>
</filter>
我的代码现在再次正常运行(不,谢谢TrendMicro)
答案 1 :(得分:0)
如果您的servlet直接为请求提供服务,那么简单的rate limiting filter就可以完成这一操作 - 而不是使用像这样的会话来改变它以使用传入请求方法+路径+ ip,然后创建第二个条目trendmicro ip。
然而,适当的Web服务器通常更好,所以如果你有一个(例如nginx或apache),那么我会考虑在那里做,或者你可以简单地阻止TrendMicro IP地址(如果它来自相同的IP)< / p>