裝飾器
使用者的瀏覽器客戶端與動態網頁伺服器端連繫與溝通看似簡單,事實上非常不容易。世界上同時數十億個網路使用者,要將他們相互建立關係並不是件容易的事。在網頁程式中有眾多方法暫存與客戶端的互動記錄,首先可以利用Request.Session物件來進行,這也是本次的主題。首先請建立新網頁「ch05.jsp」,並且將裝飾器「temp.jsp」內容完整複製到新建立的「ch05.jsp」中。未建立投票機制
沒有建立正式的Session機制的情況下,伺服器雖然在底層有基本資料使得客戶端不至於斷線。但是在應用程式的使用層級仍然不記錄曾經投票的連線。這使得投票的動作可以無限制的從遠端執行,這是很明顯的問題。早期的網路文化時常存在這個漏洞,經營者有意或無意的釋放個漏洞以期待產生驚人的數字。事實上這只要在資料庫端利用公式計算就可以達到灌水效果,現在實名制度和其他記名方式都能夠準確的建立投票機制。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | <%@ 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 = "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是不是存在,若存在就不進行計數的動作。
1 2 3 4 5 6 7 | 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是否存在,若存在即跳出警告。
1 2 3 | <% if (session.getAttribute( "voted" )!= null ) { %> <script>alert( "已投票" );</script> <%} %> |
完整的程式碼請參考
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | <%@ 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 = "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 > |
沒有留言:
張貼留言