參考地址:http://blog.csdn.net/hlk_1135/article/details/52809468
B/S頁面間通信
HTTP是無狀態的協議。Web頁面本身無法向下一個頁面傳遞信息,如果需要讓下一個頁面得知該頁面中的值,除非通過服務器。因此,Web頁面保持狀態並傳遞給其它頁面,是一個重要的技術。
Web頁面之間傳遞數據,是Web程序的重要功能
在
HTTP協議中一共有4種方法來完成這件事情:
1)URL傳值;
2)表單傳值;
3)Cookie方法;
4)Session方法;
一、URL傳值
將頁面1中的值傳給頁面2
1. index.jsp頁面
- <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <title>My JSP 'index.jsp' starting page</title>
- <meta http-equiv="pragma" content="no-cache">
- <meta http-equiv="cache-control" content="no-cache">
- <meta http-equiv="expires" content="0">
- <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
- <meta http-equiv="description" content="This is my page">
- </head>
- <body>
- <%
- String str="318";
- int number=Integer.parseInt(str);
- %>
- 該數的平方為:<%=number*number %> <hr>
- <a href="get_index.jsp?number=<%=number %>">到達get_index</a>
- </body>
- </html>
2. get_index.jsp頁面
- <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <title>My JSP 'get_index.jsp' starting page</title>
- <meta http-equiv="pragma" content="no-cache">
- <meta http-equiv="cache-control" content="no-cache">
- <meta http-equiv="expires" content="0">
- <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
- <meta http-equiv="description" content="This is my page">
- </head>
- <body>
- <%
- //獲得number
- String str=request.getParameter("number");
- int number=Integer.parseInt(str);
- %>
- 該數字的立方為:<%=number*number*number %> <hr>
- </body>
- </html>
頁面顯示結果:
優點:
簡單性和平台支持的多樣性(沒有瀏覽器不支持URL)。
缺點:
1)傳輸的數據只能是字符串,對數據類型具有一定的限制;
2)傳輸數據的值會在瀏覽器地址欄里面被看到,從保密的角度講,這是不安全的。特別是秘密性要求比較嚴格的數據,比如說密碼。
二、表單傳值
方法一中通過URL傳的值會被看到,為了避免這個問題,我們可以使用表單將頁面1中的變量傳給頁面2。
1. index.jsp:
- <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <title>My JSP 'index.jsp' starting page</title>
- <meta http-equiv="pragma" content="no-cache">
- <meta http-equiv="cache-control" content="no-cache">
- <meta http-equiv="expires" content="0">
- <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
- <meta http-equiv="description" content="This is my page">
- </head>
- <body>
- <%
- String str="10";
- int number=Integer.parseInt(str);
- %>
- 該數的平方為:<%=number*number %> <hr>
- <form action="get_index.jsp" method="post">
- <input type="text" name="number" value="<%=number %>">
- <input type="submit" value="到達get_index">
- </form>
- </body>
- </html>
2. get_index.jsp:
- <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <title>My JSP 'get_index.jsp' starting page</title>
- <meta http-equiv="pragma" content="no-cache">
- <meta http-equiv="cache-control" content="no-cache">
- <meta http-equiv="expires" content="0">
- <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
- <meta http-equiv="description" content="This is my page">
- </head>
- <body>
- <%
- //獲得number
- String str=request.getParameter("number");
- int number=Integer.parseInt(str);
- %>
- 該數字的立方為:<%=number*number*number %> <hr>
- </body>
- </html>
頁面顯示結果:
該方法順利的進行了值傳遞,並且無法看到傳遞的信息,在文本框中如果想要隱藏,將type=“text”改為type=“hidden”即可實現隱藏。
該方法的問題:
1)和URL方法類似,該方法傳輸的數據,也只能是字符串,對數據類型具有一定的限制;
2)傳輸數據的值雖然可以保證在瀏覽器地址欄里不被看到,但是在客戶端源代碼里面也會被看到,從保密的角度講,這是不安全的。對於是秘密性要求比較嚴格的數據,比如說密碼來說還是不建議用表單來進行傳輸。
三、Cookie方法
為了解決以上問題,在頁面之間進行數據傳遞的過程中,Cookie是一種常見的方法。
Cookie是一個小的文本數據,由服務器端生成,發送給客戶端瀏覽器,客戶端瀏覽器如果設置為啟用 cookie,則會將這個小文本數據保存到其目錄下的文本文件內。
客戶端下次登錄同一網站,瀏覽器則會自動將 Cookie 讀入之后,傳給服務器端。服務器端可以對該 Cookie 進行讀取並驗證(當然也可以不讀取)。
一般情況下,Cookie 中的值是以key-value的形式進行表達的。基於這個原理,上面的例子可以用 Cookie來進行。即:在第一個頁面中,將要共享的變量值保存在客戶端 Cookie 文件內,在客戶端訪問第二個頁面時,由於瀏覽器自動將 Cookie讀入之后,傳給服務器端,因此只需要第二個頁面中,由服務器端頁面讀取這個 Cookie 值即可。
Cookie是一個小的文本數據,由服務器端生成,發送給客戶端瀏覽器,客戶端瀏覽器如果設置為啟用 cookie,則會將這個小文本數據保存到其目錄下的文本文件內。
客戶端下次登錄同一網站,瀏覽器則會自動將 Cookie 讀入之后,傳給服務器端。服務器端可以對該 Cookie 進行讀取並驗證(當然也可以不讀取)。
一般情況下,Cookie 中的值是以key-value的形式進行表達的。基於這個原理,上面的例子可以用 Cookie來進行。即:在第一個頁面中,將要共享的變量值保存在客戶端 Cookie 文件內,在客戶端訪問第二個頁面時,由於瀏覽器自動將 Cookie讀入之后,傳給服務器端,因此只需要第二個頁面中,由服務器端頁面讀取這個 Cookie 值即可。
1. cookie.jsp:
- <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <title>cookie</title>
- <meta http-equiv="pragma" content="no-cache">
- <meta http-equiv="cache-control" content="no-cache">
- <meta http-equiv="expires" content="0">
- <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
- <meta http-equiv="description" content="This is my page">
- </head>
- <body>
- <h3>登陸成功</h3>
- <h3>歡迎訪問魯東大學信息與電氣工程學院</h3>
- <%
- String uri = request.getRequestURI();//返回請求行中的資源名稱
- String url = request.getRequestURL().toString();//獲得客戶端發送請求的完整url
- String ip = request.getRemoteAddr();//返回發出請求的IP地址
- String params = request.getQueryString();//返回請求行中的參數部分
- String host=request.getRemoteHost();//返回發出請求的客戶機的主機名
- int port =request.getRemotePort();//返回發出請求的客戶機的端口號。
- %>
- <%
- Cookie c=new Cookie("get_ip",ip);
- c.setMaxAge(600);
- response.addCookie(c);
- %>
- </body>
- </html>
2. get_cookie.jsp:
- <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <title>get_cookie</title>
- <meta http-equiv="pragma" content="no-cache">
- <meta http-equiv="cache-control" content="no-cache">
- <meta http-equiv="expires" content="0">
- <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
- <meta http-equiv="description" content="This is my page">
- </head>
- <body>
- <h3>從cookie.jsp頁面中獲取的信息</h3>
- <%
- String ip=null;
- Cookie[] cookies=request.getCookies();
- for(int i=0;i<cookies.length;i++) {
- if(cookies[i].getName().equals("get_ip")) {
- ip=cookies[i].getValue();
- break;
- }
- }
- %>
- ip:<%=ip %>
- </body>
- </html>
顯示結果:
1.該方法總結:
在客戶端的瀏覽器上,我們看不到任何的和傳遞的值相關的信息,說明在客戶端瀏覽器中,Cookie 中的數據是安全的。
但是就此也不能說 Cookie 是完全安全的。因為 Cookie 是以文件形式保存在客戶端的,客戶端存儲的 Cookie 文件就可能敵方獲知。如果將用戶名、密碼等敏感信息保存在Cookie內,在用戶離開客戶機時不注意清空,這些信息容易泄露,因此Cookie在保存敏感信息方面具有潛在危險。可以很清楚地看到。
Cookie的危險性來源於Cookie的被盜取。目前盜取的方法有多種:
a)利用跨站腳本技術(有關跨站腳本技術,后面的篇幅將會有介紹),將信息發給目標服務器;為了隱藏跨站腳本的 URL,甚至可以結合 Ajax(異步Javas
cript 和 XML技術)在后台竊取 Cookie;
b)通過某些軟件,竊取硬盤下的 Cookie。如前所述,當用戶訪問完某站點后,Cookie文件會存在機器的某個文件夾(如 C:\Documents and Settings\用戶名\Cookies)下,因此可以通過某些盜取和分析軟件來盜取 Cookie。
具體步驟如下:
(1)利用盜取軟件分析系統中的 Cookie,列出用戶訪問過的網站;
(2)在這些網站中尋找攻擊者感興趣的網站;
(3)從該網站的 Cookie 中獲取相應的信息。不同的軟件有不同的實現方法,有興趣的讀者可以在網上搜索相應的軟件;
c)利用客戶端腳本盜取 Cookie。在 Javascript 中有很多 API 可以讀取客戶端 Cookie,可以將這些代碼隱藏在一個程序(如畫圖片)中,很
隱秘地得到 Cookie 的值,不過,這也是跨站腳本的一種實現方式。
以上的問題並不能代表Cookie就沒有任何用處,Cookie在Web編程中應用的幾個方面:
a)Cookie 的值能夠持久化,即使客戶端機器關閉,下次打開還是可以得到里面的值。因此 Cookie 可以用來減輕用戶一些驗證工作的輸入負擔,比如用
戶名和密碼的輸入,就可以在第一次登錄成功之后,將用戶名和密碼保存在客戶端 Cookie,下次不用輸入。當然,這不安全,但是,對於一些安全要求不高的網站,Cookie 還是大有用武之地。
b)Cookie可以幫助服務器端保存多個狀態信息,但是不用服務器端專門分配存儲資源,減輕了服務器端的負擔。比如網上商店中的購物車,必須將物品和
具體客戶名稱綁定,但是放在服務器端又需要占據大量資源的情況下,可以用 Cookie 來實現,將每個物品和客戶的內容作為 Cookie 來保存在客戶端。
c)Cookie可以持久保持一些和客戶相關的信息。如很多網站上,客戶可以自主設計自己的個性化主頁,其作用是避免用戶每次都需要自己去找自己喜愛的內容,設計好之后,下次打開該網址,主頁上顯示的是客戶設置好的界面。這些設置信息保存在服務器端的話,消耗服務器端的資源,因此,可以將客戶的個性化設計保存在 Cookie 內,每一次訪問該主頁,客戶端將 Cookie 發送給服務器端,服務器根據 Cookie 的值來決定顯示給客戶端什么樣的界面。
但是就此也不能說 Cookie 是完全安全的。因為 Cookie 是以文件形式保存在客戶端的,客戶端存儲的 Cookie 文件就可能敵方獲知。如果將用戶名、密碼等敏感信息保存在Cookie內,在用戶離開客戶機時不注意清空,這些信息容易泄露,因此Cookie在保存敏感信息方面具有潛在危險。可以很清楚地看到。
Cookie的危險性來源於Cookie的被盜取。目前盜取的方法有多種:
a)利用跨站腳本技術(有關跨站腳本技術,后面的篇幅將會有介紹),將信息發給目標服務器;為了隱藏跨站腳本的 URL,甚至可以結合 Ajax(異步Javas
cript 和 XML技術)在后台竊取 Cookie;
b)通過某些軟件,竊取硬盤下的 Cookie。如前所述,當用戶訪問完某站點后,Cookie文件會存在機器的某個文件夾(如 C:\Documents and Settings\用戶名\Cookies)下,因此可以通過某些盜取和分析軟件來盜取 Cookie。
具體步驟如下:
(1)利用盜取軟件分析系統中的 Cookie,列出用戶訪問過的網站;
(2)在這些網站中尋找攻擊者感興趣的網站;
(3)從該網站的 Cookie 中獲取相應的信息。不同的軟件有不同的實現方法,有興趣的讀者可以在網上搜索相應的軟件;
c)利用客戶端腳本盜取 Cookie。在 Javascript 中有很多 API 可以讀取客戶端 Cookie,可以將這些代碼隱藏在一個程序(如畫圖片)中,很
隱秘地得到 Cookie 的值,不過,這也是跨站腳本的一種實現方式。
以上的問題並不能代表Cookie就沒有任何用處,Cookie在Web編程中應用的幾個方面:
a)Cookie 的值能夠持久化,即使客戶端機器關閉,下次打開還是可以得到里面的值。因此 Cookie 可以用來減輕用戶一些驗證工作的輸入負擔,比如用
戶名和密碼的輸入,就可以在第一次登錄成功之后,將用戶名和密碼保存在客戶端 Cookie,下次不用輸入。當然,這不安全,但是,對於一些安全要求不高的網站,Cookie 還是大有用武之地。
b)Cookie可以幫助服務器端保存多個狀態信息,但是不用服務器端專門分配存儲資源,減輕了服務器端的負擔。比如網上商店中的購物車,必須將物品和
具體客戶名稱綁定,但是放在服務器端又需要占據大量資源的情況下,可以用 Cookie 來實現,將每個物品和客戶的內容作為 Cookie 來保存在客戶端。
c)Cookie可以持久保持一些和客戶相關的信息。如很多網站上,客戶可以自主設計自己的個性化主頁,其作用是避免用戶每次都需要自己去找自己喜愛的內容,設計好之后,下次打開該網址,主頁上顯示的是客戶設置好的界面。這些設置信息保存在服務器端的話,消耗服務器端的資源,因此,可以將客戶的個性化設計保存在 Cookie 內,每一次訪問該主頁,客戶端將 Cookie 發送給服務器端,服務器根據 Cookie 的值來決定顯示給客戶端什么樣的界面。
2.解決Cookie安全的方法有很多,常見的有以下幾種:
a)替代cookie。將數據保存在服務器端,可選的是session方案;
b)及時刪除cookie。要刪除一個已經存在的Cookie,有以下幾種方法:
b_1:給一個Cookie賦以空置;
b_2:設置 Cookie 的失效時間為當前時間,讓該 Cookie 在當前頁面的瀏覽完之后就被刪除了;通過瀏覽器刪除Cookie。如在IE中,可以選擇“工具”——“Internet選項”——常規”,在里面點擊“刪除Cookies”,就可以刪除文件夾中的Cookie。
b)及時刪除cookie。要刪除一個已經存在的Cookie,有以下幾種方法:
b_1:給一個Cookie賦以空置;
b_2:設置 Cookie 的失效時間為當前時間,讓該 Cookie 在當前頁面的瀏覽完之后就被刪除了;通過瀏覽器刪除Cookie。如在IE中,可以選擇“工具”——“Internet選項”——常規”,在里面點擊“刪除Cookies”,就可以刪除文件夾中的Cookie。

四、Session方法
1、與前三種的區別:
前幾種方法在傳遞數據時,有一個共同的問題就是內容保存在客戶端里。因此,具有泄露的危險性。如果在不考慮服務器負載的情況下,將數據保存在服務端里,是一個比較好的方法,這就是session方法。
通過session.setAttribute("num",str);將str存到session中,通過session.getAttribute("num");從session中獲取num
具體的session機制,可以查看該文章。點擊查看session機制
2、服務器怎么知道要分配給它的是同一個 session 對象呢?
實際上,在客戶進行第一次訪問時,服務器端就給 session 分配了一個 sessionId,並且讓客戶端記住了這個 sessionId,客戶端訪問下一個頁面時,又將 sessionId 傳送給服務器端,服務器端根據這個 sessionId 來找到前一個頁面用的 session,由此保證為同一個客戶服務的 session 對象是同一個。3、session 分配的具體過程為:
1)客戶端訪問服務器,服務器使用 session,首先檢查這個客戶端的請求里是否已包含了 sessionId;2)如果有,服務器就在內存中檢索相應 Id 的 session 來用;
3)否則服務器為該客戶端創建一個 session 並且生成一個相應的 sessionId,並且在該次響應中返回給客戶端保存。
4、session的應用:
session 經常用於保存用戶登錄狀態。比如用戶登錄成功之后要訪問好幾個頁面,但是每個頁面都需要知道是哪個用戶在登錄,此時就可以將用戶的用戶名保存在 session 內。
login.jsp:
- <%@ page language="java" import="java.util.*" pageEncoding="gb2312"%>
- 歡迎登錄郵箱
- <form action="login.jsp" method="post">
- 請您輸入賬號:<input name="account" type="text"><BR>
- 請您輸入密碼:<input name="password" type="password"><BR>
- <input type="submit" value="登錄">
- </form>
- <%
- //獲取賬號密碼
- String account = request.getParameter("account");
- String password = request.getParameter("password");
- if(account!=null)
- {
- //驗證賬號密碼,假如賬號密碼相同表示登錄成功
- if(account.equals(password))
- {
- //放入 session,跳轉到下一個頁面
- session.setAttribute("account",account);
- response.sendRedirect("loginResult.jsp");
- }
- else
- {
- out.println("登錄不成功");
- }
- }
- %>
- <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
- <%
- if(session.getAttribute("account")==null)
- {
- response.sendRedirect("login.jsp");
- }
- %>
- 歡迎<%=session.getAttribute("account") %>來到郵箱!
提示:在大項目中有許多頁面可能會用到session檢查。針對這個問題,可以用兩種方法解決。
1)將session代碼檢查寫成一個文件。
2)利用過濾器
5、session的不安全因素
session 機制最大的不安全因素是 sessionId 可以被攻擊者截獲,如果攻擊者通過一些手段知道了 sessionId,由於 sessionId 是客戶端尋找服務器端 session 對象的唯一標識,攻擊者就有可能根據 sesionId 來訪問服務器端的 session 對象,得知 session 中的內容,從而實施攻擊。在 session 機制中,很多人認為:只要瀏覽器關閉,會話結束,session 就消失了。其實不然,瀏覽器關閉,會話結束,對於客戶端來說,已經無法直接再訪問原來的那個 session,但並不代表 session 在服務器端會馬上消失。除非程序通知服務器刪除一個 session,否則服務器會一直保留這個 session 對象,直到 session 超時失效,被垃圾收集機制收集掉。但是令人遺憾的是,客戶在關閉瀏覽器時,一般不會通知服務器。由於關閉瀏覽器不會導致 session 被刪除,因此,客戶端關閉之后,session 還未失效的情況下,就給了攻擊者以機會來獲取 session 中的內容。
雖然 sessionId 是隨機的長字符串,通常比較難被猜測到,這在某種程度上可以加強其安全性,但是一旦被攻擊者獲得,就可以進行一些攻擊活動,如:攻擊者獲取客戶 sessionId,然后攻擊者自行偽造一個相同的 sessionId,訪問服務器,實際上等價於偽裝成該用戶進行操作。
6、防止以上因為 sessionId 泄露而造成的安全問題
1):在服務器端,可以在客戶端登陸系統時,盡量不要使用單一的 sessionId 對用戶登陸進行驗證。可以通過一定的手段,不時地變更用戶的 sessionId;
2):在客戶端,應該在瀏覽器關閉時刪除服務器端的 session,也就是說在關閉時必須通知服務器端。最簡單的方法,可以用 Javascript 實現。
