標籤:des style blog http color 使用
首先受到struts token的啟發,產生了用戶端發起的ajax請求進行驗證的想法,大致思路是用戶端每次請求產生一個key ,然後服務端接收到key,然後解析,判斷是否為合法key, 對於不帶key 或者驗證失敗的直接攔截下來,從而減輕伺服器的壓力,好了廢話不多說,上代碼
首先我使用的是struts2的攔截器,(ps:不知道的度娘告訴你)
繼承 AbstractInterceptor 實現init()和 intercept() ,從字面意思上去理解這兩個方法 初始化 和攔截
第一個方法 就是從設定檔讀取配置資訊,沒什麼特別的
第二個方法 主要是分為兩部分驗證key 我這裡 分 ajax 訪問和普通方法 看代碼
public String intercept(ActionInvocation invocation) throws Exception { String rs = null; if (isTokenInterceptor) { boolean flag = false; String msg = "{_success : false,_operationMsg:‘非正常訪問,屬於非法用戶端!‘}"; ActionContext ac = invocation.getInvocationContext(); HttpServletRequest request = (HttpServletRequest) ac.get("com.opensymphony.xwork2.dispatcher.HttpServletRequest"); if (PublicUtil.isNotEmpty(freeURL)) { String urlValue[] = freeURL.split(","); if (PublicUtil.isNotEmpty(urlValue)) { String as[]; int j = (as = urlValue).length; for (int i = 0; i < j; i++) { String url = as[i]; if (request.getRequestURI().indexOf(url) != -1) { flag = true; break; } } } } if(!flag){ HttpSession session = request.getSession(); String requestToken; HttpServletResponse response; try { response = (HttpServletResponse) ac.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"); String requestType = request.getHeader("X-Requested-With"); if("XMLHttpRequest".equals(requestType)){ //驗證是否為ajax 請求 requestToken = request.getHeader(TOKEN_NAME); if(PublicUtil.isNotEmpty(requestToken) && requestToken.indexOf("||")!=-1){ String token = (String) session.getAttribute(SESSION_TOKEN); if (!requestToken.equals(token)) { flag = true; } else { logger.warn(PublicUtil.toAppendStr( "用戶端表單防重複驗證生效:用戶端多次提交 requestToken:", requestToken)); msg = "{_success : false,_operationMsg : ‘對不起,網路異常,請重新提交嘗試!‘}"; } session.setAttribute(SESSION_TOKEN, requestToken); } }else{ //普通請求 通過讀取cookie 來驗證 requestToken = CookieUtil.getCookie(request, TOKEN_NAME); if(PublicUtil.isEmpty(requestToken)){ requestToken = DesUtil.getRequestKey(); } if(PublicUtil.match("^[0-9]{8}$", DesUtil.strDec(requestToken))){ String token = (String) session.getAttribute(COOKIE_TOKEN); if(PublicUtil.isEmpty(token)){ token = requestToken; } if (requestToken.equals(token)) { flag = true; } else { logger.warn(PublicUtil.toAppendStr( "用戶端表單防重複驗證生效:用戶端多次提交 requestToken:", requestToken, " url:", request.getRequestURI())); msg = "{_success : false,_operationMsg : ‘對不起,網路異常,請重新提交嘗試!‘}"; } } String nextToken = DesUtil.getRequestKey(); CookieUtil.setCookie(response, TOKEN_NAME, nextToken); session.setAttribute(COOKIE_TOKEN, nextToken); flag = true; } } catch (IllegalStateException e) { flag = false; msg = PublicUtil.toAppendStr( "{_success : false,_operationMsg : ‘Error creating HttpSession due response is commited to client. You can use the CreateSessionInterceptor or create the HttpSession from your action before the result is rendered to the client: ", e.getMessage(), "‘}"); e.printStackTrace(); } } if (flag) { rs = invocation.invoke(); } else { HttpServletResponse response = (HttpServletResponse) ac .get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"); response.setCharacterEncoding("UTF-8"); response.getWriter().write(msg); } } else { rs = invocation.invoke(); } return rs; }
前台, 對於ajax 提交,我採用的header 夾帶驗證key的方式進行傳遞, 因為項目中使用的jquery 所以 我直接重寫 $.ajax 方法就搞定了
var TOKEN_NAME = "Albedo-Requst-Token";(function($){ //備份jquery的ajax方法 var _ajax=$.ajax; //重寫jquery的ajax方法 $.ajax=function(opt){ //備份opt中error和success方法 var fn = { error:function(XMLHttpRequest, textStatus, errorThrown){}, success:function(data, textStatus){} } if(opt.error){ fn.error=opt.error; } if(opt.success){ fn.success=opt.success; } //擴充增強處理 var _opt = $.extend(opt,{ beforeSend: function(request) { request.setRequestHeader("Albedo-Requst-Token", getRequestKey()+"||"+opt.url); //產生一個時間不同時的唯一key 特別注意 時間不同,如果時間相同,可以應該一樣 }, error:function(XMLHttpRequest, textStatus, errorThrown){ //錯誤方法增強處理 fn.error(XMLHttpRequest, textStatus, errorThrown); }, success:function(data, textStatus){ //成功回調方法增強處理 if(typeof data=="string"){ //對於被攔截下來的請求統一做提示 try{ eval("var rs = " + data); if(rs && rs._success == false && rs._operationMsg){ if(!g_showTip) alert(rs._operationMsg); else setTimeout(function(){g_showTip(rs._operationMsg);},500); } }catch(e){} } fn.success(data, textStatus); } }); _ajax(_opt); };})(jQuery);
當然,沒有用這個的,也不要跪,至少還有?後面傳參也是可以搞定的 ^_^,
這樣之後就搞定了,如果一個頁面連續對一個地址發起幾次請求,那麼這樣之後只會有第一個請求成功,之後的請求全部會被攔截下來
ps: 個人見解,有不足之處,可以提出來大家參考