裝飾器
使用者的瀏覽器客戶端與動態網頁伺服器端連繫與溝通看似簡單,事實上非常不容易。世界上同時數十億個網路使用者,要將他們相互建立關係並不是件容易的事。在網頁程式中有眾多方法暫存與客戶端的互動記錄,首先可以利用Request.Session物件來進行,這也是本次的主題。首先請建立新網頁「ch05.jsp」,並且將裝飾器「temp.jsp」內容完整複製到新建立的「ch05.jsp」中。未建立投票機制
沒有建立正式的Session機制的情況下,伺服器雖然在底層有基本資料使得客戶端不至於斷線。但是在應用程式的使用層級仍然不記錄曾經投票的連線。這使得投票的動作可以無限制的從遠端執行,這是很明顯的問題。早期的網路文化時常存在這個漏洞,經營者有意或無意的釋放個漏洞以期待產生驚人的數字。事實上這只要在資料庫端利用公式計算就可以達到灌水效果,現在實名制度和其他記名方式都能夠準確的建立投票機制。<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <%@include file="conn.jsp"%><!-- 資料庫連線 --> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>討論區最有價值的主題票選</title><!-- 瀏覽器標題 --> <link href="style.css" rel="stylesheet"> <!-- 自定義裝飾 --> <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap-responsive.min.css" rel="stylesheet"> <script src="http://code.jquery.com/jquery-1.12.4.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script> </head> <body> <%@include file="menu.jsp"%><!-- 選單 --> <div class="container"> <div class="page-header"> <h1>討論區最有價值的主題票選</h1><!-- 網頁標題 --> </div> <% request.setCharacterEncoding("UTF-8");//將輸入編碼設定為UTF-8 response.setCharacterEncoding("UTF-8");//將輸出編碼設定為UTF-8 try {//建立資料表以try,catch的方式,因CREATE TABLE IF NOT EXISTS在不同資料庫中有錯誤的風險與舊資料被清除的問題 stat.executeUpdate("CREATE TABLE 'bbs_vote' ('bbs' INTEGER,'cnt' INTEGER,'key' TEXT,PRIMARY KEY('bbs'));"); } catch (Exception e) {} if(request.getParameter("Oid")!=null){ try{ stat.executeUpdate("INSERT INTO bbs_vote(bbs, cnt)VALUES("+request.getParameter("Oid")+", 0);"); }catch(Exception e){} stat.executeUpdate("UPDATE bbs_vote SET cnt=cnt+1 WHERE bbs="+request.getParameter("Oid")); } sql = "SELECT b.*,(SELECT COUNT(*)FROM bbs_feedback WHERE bbs=b.Oid)as f_cnt, IFNULL((SELECT cnt FROM bbs_vote WHERE bbs=b.Oid),0)as v_cnt FROM bbs b";//建立查詢字串 rs = stat.executeQuery(sql);//查詢結果 %> <form action="ch05.jsp" method="GET"> <%while (rs.next()) {%> <h2> <input type="radio" name="Oid" value="<%=rs.getString("Oid")%>"> <a href="ch05.jsp?Oid=<%=rs.getString("Oid")%>"><%=rs.getString("title")%></a> <small><%=rs.getString("user")%>, <%=rs.getString("f_cnt")%>篇回覆</small> <small><%=rs.getString("v_cnt")%>票</small> </h2> <hr /> <%}%> <button class="btn" type="submit">確定</button> </form> </div> <%@include file="foot.jsp"%><!-- 頁尾 --> </body> </html>
建立投票機制
沒有記名的資訊系統,通常無法做精準的投票。以下程式碼以基本的session方式,驗證使用者在這個網頁的狀況。在第1次投票成功時,計錄1個名為voted的session。在此同時也判斷voted是不是存在,若存在就不進行計數的動作。
if(request.getParameter("Oid")!=null&& session.getAttribute("voted")==null){ try{ stat.executeUpdate("INSERT INTO bbs_vote(bbs, cnt)VALUES("+request.getParameter("Oid")+", 0);"); }catch(Exception e){} stat.executeUpdate("UPDATE bbs_vote SET cnt=cnt+1 WHERE bbs="+request.getParameter("Oid")); session.setAttribute("voted", true); }
網頁本體加上檢查voted是否存在,若存在即跳出警告。
<%if(session.getAttribute("voted")!=null) { %> <script>alert("已投票");</script> <%} %>
完整的程式碼請參考
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <%@include file="conn.jsp"%><!-- 資料庫連線 --> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>討論區最有價值的主題票選</title><!-- 瀏覽器標題 --> <link href="style.css" rel="stylesheet"> <!-- 自定義裝飾 --> <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap-responsive.min.css" rel="stylesheet"> <script src="http://code.jquery.com/jquery-1.12.4.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script> </head> <body> <%@include file="menu.jsp"%><!-- 選單 --> <div class="container"> <div class="page-header"> <h1>討論區最有價值的主題票選</h1><!-- 網頁標題 --> </div> <% request.setCharacterEncoding("UTF-8");//將輸入編碼設定為UTF-8 response.setCharacterEncoding("UTF-8");//將輸出編碼設定為UTF-8 try {//建立資料表以try,catch的方式,因CREATE TABLE IF NOT EXISTS在不同資料庫中有錯誤的風險與舊資料被清除的問題 stat.executeUpdate("CREATE TABLE 'bbs_vote' ('bbs' INTEGER,'cnt' INTEGER,'key' TEXT,PRIMARY KEY('bbs'));"); } catch (Exception e) {} if(request.getParameter("Oid")!=null&& session.getAttribute("voted")==null){ try{ stat.executeUpdate("INSERT INTO bbs_vote(bbs, cnt)VALUES("+request.getParameter("Oid")+", 0);"); }catch(Exception e){} stat.executeUpdate("UPDATE bbs_vote SET cnt=cnt+1 WHERE bbs="+request.getParameter("Oid")); session.setAttribute("voted", true); } sql = "SELECT b.*,(SELECT COUNT(*)FROM bbs_feedback WHERE bbs=b.Oid)as f_cnt, IFNULL((SELECT cnt FROM bbs_vote WHERE bbs=b.Oid),0)as v_cnt FROM bbs b";//建立查詢字串 rs = stat.executeQuery(sql);//查詢結果 %> <%if(session.getAttribute("voted")!=null) { %> <script>alert("已投票");</script> <%} %> <form action="ch05.jsp" method="GET"> <%while (rs.next()) {%> <h2> <input type="radio" name="Oid" value="<%=rs.getString("Oid")%>"> <a href="ch05.jsp?Oid=<%=rs.getString("Oid")%>"><%=rs.getString("title")%></a> <small><%=rs.getString("user")%>, <%=rs.getString("f_cnt")%>篇回覆</small> <small><%=rs.getString("v_cnt")%>票</small> </h2> <hr /> <%}%> <button class="btn" type="submit">確定</button> </form> </div> <%@include file="foot.jsp"%><!-- 頁尾 --> </body> </html>
沒有留言:
張貼留言