Struts2 過濾CSRF攻擊的一種解決方案
阿新 • • 發佈:2019-01-08
CSRF(Cross-site request forgery跨站請求偽造,也被稱為“One Click Attack”或者Session Riding,通常縮寫為CSRF或者XSRF,是一種對網站?的惡意利用。儘管聽起來像跨站指令碼(XSS),但它與XSS非常不同,並且攻擊方式幾乎相左。XSS利用站點內的信任使用者,而CSRF則通過偽裝來自受信任使用者的請求來利用受信任的網站。與XSS攻擊相比,CSRF攻擊往往不大流行(因此對其進行防範的資源也相當稀少)和難以防範,所以被認為比XSS更具危險性。
它的防禦方案包括如下四種:
1.檢查http referer是否來自同一個域
2.限制session cookie的生命週期
3.驗證碼
4.使用token
在struts下自帶了許多標籤庫
其中就有 s:token ,這個可以生成一次性token,把這個標籤放在 s:form 裡面可以在提交的時候自動帶上token值;
<s:form action="login.action">
<s:token name="token"></s:token>
<s:fielderror name="errorInfo"></s:fielderror>
<s:textfield name="username" key="user"></s:textfield >
<s:textfield name="password" key="pass"></s:textfield>
<s:submit key="login"></s:submit>
</s:form>
然後在struts.xml的對應的action中引用就好了
<param name="excludeMethods">....</param> //這裡可以配置token攔截器的排隊方法
<interceptor-ref name="token" >
param name="excludeMethods">....</param> //這裡可以配置token攔截器的排隊方法
</interceptor-ref>
<result name=“invaild.token">/***.jsp</result>
一般情況下這個攔截器就配置完了
但是這個攔截器會把這個action的post 方法和get方法同時攔截掉。
如果我們只需要攔截post方法的請求應該怎麼處理呢?
在這裡我們自己實現一個攔截器只攔截post方法
實現如下
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.interceptor.TokenInterceptor;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class CsrfInterceptor extends AbstractInterceptor{
@Override
public String intercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
ActionContext actionContext = invocation.getInvocationContext();
HttpServletRequest request = (HttpServletRequest)actionContext.get(ServletActionContext.HTTP_REQUEST);
if (request.getMethod().equals("GET")) {
return invocation.invoke();
}
String tokenName = request.getParameter("struts.token.name");
if (tokenName == null) {
return "invalid.token";
}
String token = request.getParameter(tokenName);
if (token == null) {
return "invalid.token";
}
String correctToken = (String) request.getSession().getAttribute("struts.tokens." + tokenName);
if (token.equals(correctToken)) {
actionContext.getSession().put("struts.tokens" + tokenName , null);
return invocation.invoke();
}else {
return "invalid.token";
}
}
}
我們可以用配置一般攔截器的方法配置此攔截器,在此不再敘述。
需要注意的一點是,須在struts.xml下 action標籤下配置此項
<result name="invalid.token">jsp/tokenError.jsp</result>
表示token值驗證失敗後的處理情況,具體實現看實際專案的需要