在Apache Tomcat servlet中處理來自同一客戶端的重複GET請求的最佳策略是什麼?在Tomcat servlet中處理重複GET請求(由Trendmicro引起)
基本上,我越來越有2請求的幾秒鐘分開,從客戶端的真實IP第一,從趨勢科技服務器第2(這似乎是描述here是同樣的效果。
現在我的servlet忠實地服務於這兩個請求,但稍後會產生問題(因爲它調用另一個遠程服務,這很可能無法處理這種情況)
所以問題是,如何阻止第二個請求?任何其他策略來解決這個問題?
謝謝!
在Apache Tomcat servlet中處理來自同一客戶端的重複GET請求的最佳策略是什麼?在Tomcat servlet中處理重複GET請求(由Trendmicro引起)
基本上,我越來越有2請求的幾秒鐘分開,從客戶端的真實IP第一,從趨勢科技服務器第2(這似乎是描述here是同樣的效果。
現在我的servlet忠實地服務於這兩個請求,但稍後會產生問題(因爲它調用另一個遠程服務,這很可能無法處理這種情況)
所以問題是,如何阻止第二個請求?任何其他策略來解決這個問題?
謝謝!
如果你的servlet直接爲請求提供服務,一個簡單的rate limiting filter可以做到這一點 - 而不是像這樣使用會話來改變它使用傳入請求方法+路徑+ IP,然後爲trendmicro ip創建第二個條目。
然而,正確的網絡服務器通常更好,所以如果你有一個(例如nginx或apache),那麼我會考慮在那裏做,或者你可以簡單地阻止TrendMicro IP地址(如果它來自同一個IP)
所以我剛剛發現,這也造成了我的網站上的問題。我存儲了客戶在會話中請求的當前信息,但我收到了一些看似隨機情況的報告,其中用戶將查看一個客戶信息,查看其他客戶信息,添加評論,但評論最終結束在第一客戶記錄。
我今天發現了罪魁禍首。它是趨勢科技(TrendMicro),將真實用戶查看第二客戶信息和添加評論之間的第一個客戶記錄視爲呼叫。他們也欺騙了cookie,這是主要問題。
IE瀏覽器。 1)真正的IP電話用戶1個信息(信息被存儲在會話)
2)實時IP呼叫客戶2信息(信息被存儲在會話,免去客戶1個資訊)
3)趨勢科技IP電話客戶1信息(信息被存儲在會話,免去客戶2信息)
4)真正的IP加評論,這被添加到存儲在會話,現在,多虧了趨勢科技,爲客戶1
的客戶解? - 我添加了一個檢查,以確保我們只處理來自登錄的IP地址的呼叫。
要做到這一點,您需要做2件事。
1)在您的登錄代碼,您已經驗證的登錄憑據後,使用此代碼存儲用戶IP地址的會話:
session.setAttribute("LoginIPAddress", request.getRemoteAddr());
接下來,編寫一個實現的javax.servlet類。過濾界面。
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」)。等於(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 IP(s)。 由於此服務僅由註冊用戶調用,因此我現在實現了一個過濾器,該過濾器使用用戶的ID在第一個(實際)請求仍在運行時阻止重複請求。 – user1703668 2015-02-06 15:07:12