日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

开发中经常碰到的问题cookie和session问题,今天一并解决

發(fā)布時間:2025/3/20 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 开发中经常碰到的问题cookie和session问题,今天一并解决 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

點擊上方“好好學(xué)java”,選擇“置頂公眾號”

優(yōu)秀學(xué)習(xí)資源、干貨第一時間送達!

?精彩內(nèi)容?

java實戰(zhàn)練習(xí)項目教程

2018微服務(wù)資源springboot、springcloud、docker、dubbo實戰(zhàn)等傾心分享

2018年java架構(gòu)師全套學(xué)習(xí)教程

最新大數(shù)據(jù)培訓(xùn)完整視頻教程

2018年java最新全套培訓(xùn)學(xué)習(xí)教程

一、會話的概念

會話可簡單理解為:用戶開一個瀏覽器,點擊多個超鏈接,訪問服務(wù)器多個web資源,然后關(guān)閉瀏覽器,整個過程稱之為一個會話

二、會話過程中要解決的一些問題

每個用戶在使用瀏覽器與服務(wù)器進行會話的過程中,不可避免各自會產(chǎn)生一些數(shù)據(jù),程序要想辦法為每個用戶保存這些數(shù)據(jù)。

三、保存會話數(shù)據(jù)的兩種技術(shù)

1、Cookie

Cookie意為"甜餅",是由W3C組織提出,最早由Netscape社區(qū)發(fā)展的一種機制。目前Cookie已經(jīng)成為標準,所有的主流瀏覽器如IE、Netscape、Firefox、Opera等都支持Cookie。

由于HTTP是一種無狀態(tài)的協(xié)議,服務(wù)器單從網(wǎng)絡(luò)連接上無從知道客戶身份。怎么辦呢?就給客戶端們頒發(fā)一個通行證吧,每人一個,無論誰訪問都必須攜帶自己通行證。這樣服務(wù)器就能從通行證上確認客戶身份了。這就是Cookie的工作原理。

Cookie實際上是一小段的文本信息。客戶端請求服務(wù)器,如果服務(wù)器需要記錄該用戶狀態(tài),就使用response向客戶端瀏覽器頒發(fā)一個Cookie。客戶端瀏覽器會把Cookie保存起來。當瀏覽器再請求該網(wǎng)站時,瀏覽器把請求的網(wǎng)址連同該Cookie一同提交給服務(wù)器。服務(wù)器檢查該Cookie,以此來辨認用戶狀態(tài)。服務(wù)器還可以根據(jù)需要修改Cookie的內(nèi)容。

2、Session

Session是服務(wù)器端技術(shù),利用這個技術(shù),服務(wù)器在運行時可以為每一個用戶的瀏覽器創(chuàng)建一個其獨享的session對象,由于session為用戶瀏覽器獨享,所以用戶在訪問服務(wù)器的web資源時,可以把各自的數(shù)據(jù)放在各自的session中,當用戶再去訪問服務(wù)器中的其它web資源時,其它web資源再從用戶各自的session中取出數(shù)據(jù)為用戶服務(wù)。

四、Cookie類的主要方法

int getMaxAge()返回Cookie過期之前的最大時間,以秒計算。
void setMaxAge(intexpiry)以秒計算,設(shè)置Cookie過期時間。
String getName()返回Cookie的名字。名字和值是我們始終關(guān)心的兩個部分,筆者會在后面詳細介紹 getName/setName。
void setValue(String newValue)Cookie創(chuàng)建后設(shè)置一個新的值。
String getValue()返回Cookie的值。筆者也將在后面詳細介紹getValue/setValue。
void setDomain(String pattern)設(shè)置cookie中Cookie適用的域名
String getDomain()返回Cookie中Cookie適用的域名. 使用getDomain() 方法可以指示瀏覽器把Cookie返回給同 一域內(nèi)的其他服務(wù)器,而通常Cookie只返回給與發(fā)送它的服務(wù)器名字完全相同的服務(wù)器。注意域名必須以點開始(例如.yesky.com)
void setPath(String uri)指定Cookie適用的路徑。
String getPath()返回Cookie適用的路徑。如果不指定路徑,Cookie將返回給當前頁面所在目錄及其子目錄下 的所有頁面。
void setSecure(boolean flag)指出瀏覽器使用的安全協(xié)議,例如HTTPS或SSL。
boolean getSecure()如果瀏覽器通過安全協(xié)議發(fā)送cookies將返回true值,如果瀏覽器使用標準協(xié)議則返回false值。
void setVersion(int v)Cookie所遵從的協(xié)議版本。
int getVersion()返回Cookie所遵從的協(xié)議版本。
void setComment(String purpose)設(shè)置cookie中注釋。
String getComment()返回Cookie中注釋,如果沒有注釋的話將返回空值。
Cookie(String name, String value)實例化Cookie對象,傳入cooke名稱和cookie的值。

response接口也中定義了一個addCookie方法,它用于在其響應(yīng)頭中增加一個相應(yīng)的Set-Cookie頭字段。 同樣,request接口中也定義了一個getCookies方法,它用于獲取客戶端提交的Cookie。

五、Cookie使用

1、使用cookie記錄用戶上一次訪問的時間

public?class?CookieDemo?extends?HttpServlet{private?static?final?long?serialVersionUID?=?5757885987685925915L;@Overrideprotected?void?doGet(HttpServletRequest?req,?HttpServletResponse?resp)?throws?ServletException,?IOException?{doPost(req,?resp);}@Overrideprotected?void?doPost(HttpServletRequest?req,?HttpServletResponse?resp)?throws?ServletException,?IOException?{//設(shè)置服務(wù)器以UTF-8編碼輸出resp.setCharacterEncoding("UTF-8");//設(shè)置瀏覽器以UTF-8編碼進行接收resp.setContentType("text/html;charset=UTF-8");PrintWriter?out?=?resp.getWriter();//獲取Cookie數(shù)組Cookie[]?cookie?=?req.getCookies();if(cookie?==?null){out.write("這是你的第一次訪問!");}?else?{for?(Cookie?ck?:?cookie)?{if(ck.getName().equals("cookieName")){//獲取Cookie里面保存的數(shù)據(jù)Long?time?=?Long.parseLong(ck.getValue());Date?date?=?new?Date(time);out.write("上次訪問時間:"?+?date.toLocaleString());}}}//創(chuàng)建一個cookie,cookie的名字是cookieNameCookie?cookies?=?new?Cookie("cookieName",?System.currentTimeMillis()+"");//設(shè)置Cookie的有效期為1天,這樣即使關(guān)閉了瀏覽器,下次再訪問時,也依然可以通過cookie獲取用戶上一次訪問的時間。cookies.setMaxAge(24*60*60);//將cookie對象添加到response對象中resp.addCookie(cookies);} }

第一次訪問時,如下所示:

image

再次訪問:

image

2、刪除Cookie

public?class?CookieDemo?extends?HttpServlet?{@Overrideprotected?void?doGet(HttpServletRequest?req,?HttpServletResponse?resp)throws?ServletException,?IOException?{doPost(req,?resp);}@Overrideprotected?void?doPost(HttpServletRequest?req,?HttpServletResponse?resp)throws?ServletException,?IOException?{//創(chuàng)建一個名字為lastAccessTime的cookieCookie?cookie?=?new?Cookie("lastAccessTime",?System.currentTimeMillis()+"");//將cookie的有效期設(shè)置為0,命令瀏覽器刪除該cookiecookie.setMaxAge(0);req.addCookie(cookie);} }

3、cookie中存/取中文

public?class?CookieDemo2?extends?HttpServlet{private?static?final?long?serialVersionUID?=?5757885987685925915L;@Overrideprotected?void?doGet(HttpServletRequest?req,?HttpServletResponse?resp)?throws?ServletException,?IOException?{doPost(req,?resp);}@Overrideprotected?void?doPost(HttpServletRequest?req,?HttpServletResponse?resp)?throws?ServletException,?IOException?{//設(shè)置服務(wù)器以UTF-8編碼輸出resp.setCharacterEncoding("UTF-8");//設(shè)置瀏覽器以UTF-8編碼進行接收resp.setContentType("text/html;charset=UTF-8");PrintWriter?out?=?resp.getWriter();//創(chuàng)建一個cookie,cookie的名字是cookieName//存儲中文時,使用URLEncoder類里面的encode(String?s,?String?enc)方法進行中文轉(zhuǎn)碼Cookie?cookies?=?new?Cookie("cookieName",?URLEncoder.encode("哎喲!不錯喲",?"UTF-8"));//將cookie對象添加到response對象中resp.addCookie(cookies);//獲取Cookie數(shù)組Cookie[]?cookie?=?req.getCookies();if(cookie?!=?null){for?(Cookie?ck?:?cookie)?{if(ck.getName().equals("cookieName")){//獲取Cookie里面保存的數(shù)據(jù)String?text?=?ck.getValue();//使用URLDecoder類里面的decode(String?s,?String?enc)進行解碼out.write("存儲的中文數(shù)據(jù):"?+?URLDecoder.decode(text,?"UTF-8"));}}}} }

結(jié)果如下:

image

Cookie注意細節(jié)

1,一個Cookie只能標識一種信息,它至少含有一個標識該信息的名稱(NAME)和設(shè)置值(VALUE)。

2,一個WEB站點可以給一個WEB瀏覽器發(fā)送多個Cookie,一個WEB瀏覽器也可以存儲多個WEB站點提供的Cookie。

3,瀏覽器一般只允許存放300個Cookie,每個站點最多存放20個Cookie,每個Cookie的大小限制為4KB。

4,如果創(chuàng)建了一個cookie,并將他發(fā)送到瀏覽器,默認情況下它是一個會話級別的cookie(即存儲在瀏覽器的內(nèi)存中),用戶退出瀏覽器之后即被刪除。若希望瀏覽器將該cookie存儲在磁盤上,則需要使用maxAge,并給出一個以秒為單位的時間。將最大時效設(shè)為0則是命令瀏覽器刪除該cookie。

六、Session簡單介紹

在WEB開發(fā)中,服務(wù)器可以為每個用戶瀏覽器創(chuàng)建一個會話對象(session對象),注意:一個瀏覽器獨占一個session對象(默認情況下)。因此,在需要保存用戶數(shù)據(jù)時,服務(wù)器程序可以把用戶數(shù)據(jù)寫到用戶瀏覽器獨占的session中,當用戶使用瀏覽器訪問其它程序時,其它程序可以從用戶的session中取出該用戶的數(shù)據(jù),為用戶服務(wù)。

Session和Cookie的主要區(qū)別

1,Cookie是把用戶的數(shù)據(jù)寫給用戶的瀏覽器。

2,Session技術(shù)把用戶的數(shù)據(jù)寫到用戶獨占的session中。

3,Session對象由服務(wù)器創(chuàng)建,開發(fā)人員可以調(diào)用request對象的getSession方法得到session對象。

七、Session基礎(chǔ)知識

Session是服務(wù)器端技術(shù),利用這個技術(shù),服務(wù)器在運行時可以為每一個用戶的瀏覽器創(chuàng)建一個其獨享的session對象,由于session為用戶瀏覽器獨享,所以用戶在訪問服務(wù)器的web資源時,可以把各自的數(shù)據(jù)放在各自的session中,當用戶再去訪問服務(wù)器中的其它web資源時,其它web資源再從用戶各自的session中取出數(shù)據(jù)為用戶服務(wù)。

當用戶打開瀏覽器,訪問某個網(wǎng)站操作session時,服務(wù)器就會在服務(wù)器的內(nèi)存為該瀏覽器分配一個session對象,該session對象被這個瀏覽器獨占。

這個session對象也可以看做是一個容器,session默認存在時間為30min,你可以修改。

1、Session可以用來做什么

1、網(wǎng)上商城中的購物車

2、保存登錄用戶的信息

3、將某些數(shù)據(jù)放入到Session中,供同一用戶的各個頁面使用

4、防止用戶非法登錄到某個頁面。

2、Session基本使用

request.getSession()返回這個request綁定的session對象,如果沒有,則創(chuàng)建一個
request.getSession(boolean create)返回這個request綁定的session對象,如果沒有,則根據(jù)create的值決定是否創(chuàng)建一個
session.setAttribute(String name,Object val)向session中添加屬性
session.getAttribute(String name)從session中得到某個屬性
session.removeAttribute(String name)從session中刪除某個屬性
session.setMaxInactiveInterval()設(shè)置Session的生命周期(單位秒),Session的生命周期默認是30min
session.invalidate()清除所有session
session.removeAttribute(String name)刪除指定名稱的session

Servlet1:

public?class?Servlet1?extends?HttpServlet?{private?static?final?long?serialVersionUID?=?-8236507185410764108L;@Overrideprotected?void?doGet(HttpServletRequest?req,?HttpServletResponse?resp)?throws?ServletException,?IOException?{doPost(req,?resp);}@Overrideprotected?void?doPost(HttpServletRequest?req,?HttpServletResponse?resp)?throws?ServletException,?IOException?{//獲取sessionHttpSession?session?=?req.getSession();//將數(shù)據(jù)存儲到session中session.setAttribute("name",?"Zender");} }

Servlet2:

public?class?Servlet2?extends?HttpServlet?{private?static?final?long?serialVersionUID?=?-8236507185410764108L;@Overrideprotected?void?doGet(HttpServletRequest?req,?HttpServletResponse?resp)?throws?ServletException,?IOException?{doPost(req,?resp);}@Overrideprotected?void?doPost(HttpServletRequest?req,?HttpServletResponse?resp)?throws?ServletException,?IOException?{//獲取sessionHttpSession?session?=?req.getSession();//獲取nameString?name?=?(String)?session.getAttribute("name");PrintWriter?out?=?resp.getWriter();out.print("name:"?+?name);} }

同一瀏覽器訪問Servlet1,再訪問Servlet2,結(jié)果如下:

image

不同瀏覽器訪問Servlet1,再訪問Servlet2,結(jié)果如下:

image

可以看到這時候name是null,也就是沒有從session對象中取出值,因為360瀏覽器并沒有運行Servlet1來創(chuàng)建Session對象,上面的session對象是Chrome瀏覽器獨占的。

3、Session生命周期

Session中的屬性的默認生命周期是30min,這個默認時間可以通過修改web.xml文件來修改

1,在Tomcat根目錄\conf\web.xml文件中修改

<session-config><session-timeout>30</session-timeout></session-config>

2,如果只需要對某一個web應(yīng)用設(shè)置,則只需要修改對應(yīng)web應(yīng)用的web.xml文件。在這個web.xml文件中添加如上的代碼:

<session-config><session-timeout>10</session-timeout></session-config>

除了設(shè)置默認生命周期之外,最重要的是在程序中設(shè)置,調(diào)用setMaxInacttiveInterval(int interval),這里的interval是以秒為單位的,而且這個方法設(shè)置的是發(fā)呆時間,比如你設(shè)置的是60秒,那么在這60秒之內(nèi)如果你沒有操作過session,它就會自動刪除,如果你操作過,不管是設(shè)置屬性還是讀取屬性,它都會從頭開始計時。

session.setMaxInactiveInterval(60);

八、Session實現(xiàn)原理

服務(wù)器是如何實現(xiàn)一個session為一個用戶瀏覽器服務(wù)的?

image

1,瀏覽器A先訪問Servlet1,這時候它創(chuàng)建了一個Session,ID號為110,然后Servlet1將這個ID號以Cookie的方式返回給瀏覽器A。

2,瀏覽器A繼續(xù)訪問Servlet2,那么這個請求會帶上Cookie值: JSESSIONID=110,然后服務(wù)器根據(jù)瀏覽器A傳遞過來的ID號找到內(nèi)存中的這個Session。

3,瀏覽器B來訪問Servlet1了,它的請求并沒有帶上 JSESSIONID這個Cookie值,由于它也要使用Session,所以服務(wù)器會新創(chuàng)建一個Session,ID號為111。

4,瀏覽器B繼續(xù)訪問Servlet2,那么這個請求會帶上Cookie值: JSESSIONID=111,然后服務(wù)器根據(jù)瀏覽器B傳遞過來的ID號找到內(nèi)存中的這個Session。

例如:

Servlet1:

public?class?Servlet1?extends?HttpServlet?{private?static?final?long?serialVersionUID?=?-8236507185410764108L;@Overrideprotected?void?doGet(HttpServletRequest?req,?HttpServletResponse?resp)?throws?ServletException,?IOException?{doPost(req,?resp);}@Overrideprotected?void?doPost(HttpServletRequest?req,?HttpServletResponse?resp)?throws?ServletException,?IOException?{//獲取sessionHttpSession?session?=?req.getSession();//將數(shù)據(jù)存儲到session中session.setAttribute("name",?"Zender");PrintWriter?out?=?resp.getWriter();out.print("create?Session?OK");} }

Servlet2:

public?class?Servlet2?extends?HttpServlet?{private?static?final?long?serialVersionUID?=?-8236507185410764108L;@Overrideprotected?void?doGet(HttpServletRequest?req,?HttpServletResponse?resp)?throws?ServletException,?IOException?{doPost(req,?resp);}@Overrideprotected?void?doPost(HttpServletRequest?req,?HttpServletResponse?resp)?throws?ServletException,?IOException?{//獲取sessionHttpSession?session?=?req.getSession();//獲取nameString?name?=?(String)?session.getAttribute("name");PrintWriter?out?=?resp.getWriter();out.println("Session?ID:"?+?session.getId());out.print("name:"?+?name);} }

第一次訪問Servlet1時,服務(wù)器會創(chuàng)建一個新的sesion,并且把session的Id以cookie的形式發(fā)送給客戶端瀏覽器,如下圖所示:

image

可以看到,Request Headers中并沒有Cookie的信息,而Response Headers中有這么一句話:

Set-Cookie:JSESSIONID=05A94199DDC64311563740CC2C78D656;?Path=/CookieAndSession/;?HttpOnly

說明這個時候服務(wù)器向客戶端通過Cookie傳遞回了 JSESSIONID這個屬性。

然后訪問Servlet2,如下圖所示:

image

可以看到Response Headers中沒有出現(xiàn)Set-Cookie這個頭,而Request Headers中帶上了Cookie這個頭:

Cookie:JSESSIONID=05A94199DDC64311563740CC2C78D656

而這個頭中正包含 JSESSIONID,并且它的值也就是我們之前Set-Cookie中 JSESSIONID的值。

這就證明了我們之前圖解的Session的原理,也就是服務(wù)器能夠為不同的瀏覽器區(qū)分不同的Session的機制。

九、Session的簡單應(yīng)用

1,用戶登錄時候驗證驗證碼

Index.jsp:

<head> <base?href="<%=basePath%>"?/> <meta?http-equiv="Content-Type"?content="text/html;charset=UTF-8"> <title>表單提交</title> <link?href="css/bootstrap.css"?rel="stylesheet"> <script?src="js/jquery-3.2.1.js"></script> <script?src="js/bootstrap.js"></script> </head> <body><form?class="form-horizontal"?action="<%=request.getContextPath()%>/CodeServlet.html"?role="form"?method="post"><div?class="form-group"><label?for="firstname"?class="col-sm-1?control-label">驗證碼</label><div?class="col-sm-3"><input?type="text"?class="form-control"?name="idCodeNum"placeholder="請輸入驗證碼"></div><img?src="idCode"?onclick="this.src+=''"?style="cursor:pointer;"?width="115"?height="30"?title="看不清?換一個"></div><div?class="form-group"><div?class="col-sm-offset-1?col-sm-3"><button?type="submit"?class="btn?btn-default">提交</button><button?type="reset"?class="btn?btn-default">重置</button></div></div></form> </body> </html>

CodeServlet:

public?class?CodeServlet?extends?HttpServlet?{private?static?final?long?serialVersionUID?=?-8236507185410764108L;@Overrideprotected?void?doGet(HttpServletRequest?req,?HttpServletResponse?resp)?throws?ServletException,?IOException?{doPost(req,?resp);}@Overrideprotected?void?doPost(HttpServletRequest?req,?HttpServletResponse?resp)?throws?ServletException,?IOException?{//獲取sessionHttpSession?session?=?req.getSession();//獲取存儲的驗證碼String?idCodeText?=?(String)?session.getAttribute("idCode");System.out.println("服務(wù)端驗證碼:"?+?idCodeText);String?idCodeNum?=?req.getParameter("idCodeNum");System.out.println("輸入的驗證碼:"?+?idCodeNum);//設(shè)置瀏覽器以UTF-8編碼進行接收resp.setContentType("text/html;charset=UTF-8");PrintWriter?out?=?resp.getWriter();if(idCodeText.equalsIgnoreCase(idCodeNum)){out.println("驗證成功!");}?else?{out.println("驗證碼錯誤!");}} }

Web.xml:

<?xml?version="1.0"?encoding="UTF-8"?> <web-app?xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://java.sun.com/xml/ns/javaee"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee?http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"id="WebApp_ID"?version="3.0"><display-name>CookieAndSession</display-name><welcome-file-list><welcome-file>index.html</welcome-file></welcome-file-list><servlet><servlet-name>CodeServlet</servlet-name><servlet-class>com.zender.session.CodeServlet</servlet-class></servlet><servlet-mapping><servlet-name>CodeServlet</servlet-name><url-pattern>/CodeServlet.html</url-pattern></servlet-mapping><!--?生成驗證碼的Servlet?--><servlet><servlet-name>ValidateCode</servlet-name><servlet-class>org.jelly.image.ValidateCode</servlet-class></servlet><servlet-mapping><servlet-name>ValidateCode</servlet-name><url-pattern>/idCode</url-pattern></servlet-mapping> </web-app>

這里使用了jelly-core-1.7.0.GA.jar來生成了驗證碼,具體使用方式請點擊:jelly-core-1.7.0.GA.jar(http://www.blogjava.net/fancydeepin/archive/2014/08/03/jelly_image.html)

訪問http://localhost:8081/CookieAndSession/index.jsp輸入驗證碼,點擊提交:

image

輸入正確驗證碼,頁面響應(yīng)結(jié)果:

image

輸入錯誤驗證碼,頁面響應(yīng)結(jié)果:

image

輸入正確驗證碼,后臺結(jié)果:

image

輸入錯誤驗證碼,后臺結(jié)果:

image

2,實現(xiàn)簡易購物車

模擬一個數(shù)據(jù)庫:

public?class?DB?{private?static?HashMap<String,?Book>?hm?=?null;private?DB(){}static{hm?=?new?LinkedHashMap<String,?Book>();Book?book1?=?new?Book(1,?"Java基礎(chǔ)");Book?book2?=?new?Book(2,?"Oracle數(shù)據(jù)庫");Book?book3?=?new?Book(3,?"C語言");Book?book4?=?new?Book(4,?"Python核心教程");Book?book5?=?new?Book(5,?"Web技術(shù)");hm.put(book1.getId()?+?""?,?book1);hm.put(book2.getId()?+?""?,?book2);hm.put(book3.getId()?+?""?,?book3);hm.put(book4.getId()?+?""?,?book4);hm.put(book5.getId()?+?""?,?book5);}/***?得到數(shù)據(jù)庫中所有的書*?@return*/public?static?HashMap<String,?Book>?getBooks(){return?hm;}/***?根據(jù)ID得到書*?@param?id*?@return*/public?static?Book?getBookById(String?id){if(hm.containsKey(id)){return?hm.get(id);}return?null;} }

BuyBookServlet這個Servlet用于購買圖書:

//顯示購買的圖書 public?class?ShowMyCartServlet?extends?HttpServlet?{private?static?final?long?serialVersionUID?=?-8236507185410764108L;@Overrideprotected?void?doGet(HttpServletRequest?req,?HttpServletResponse?resp)?throws?ServletException,?IOException?{doPost(req,?resp);}@Overrideprotected?void?doPost(HttpServletRequest?req,?HttpServletResponse?resp)?throws?ServletException,?IOException?{resp.setContentType("text/html;charset=UTF-8");PrintWriter?out?=?resp.getWriter();HttpSession?session?=?req.getSession();List<Book>?list?=?(ArrayList<Book>)?session.getAttribute("books");if(list==null?||?list.size()==0){out.write("對不起,您還沒有購買任何商品!!");return;}//顯示用戶買過的商品out.write("您買過如下商品:<br/>");for(Book?book?:?list){out.write(book.getName()?+?"<br/>");}} }

運行結(jié)果:

image

3,防止用戶非法登錄到某個頁面

比如我們的用戶管理系統(tǒng),必須要登錄成功后才能跳轉(zhuǎn)到主頁面,而不能直接繞過登錄頁面直接到主頁面,這個應(yīng)用是一個非常常見的應(yīng)用。

當在驗證用戶的控制器LoginClServlet.java驗證用戶成功后,將當前的用戶信息保存在Session對象中:

//?把user對象保存在sessionHttpSession?session?=?req.getSession();session.setAttribute("loginUser",?user);

然后在主頁面Main.java最開始的地方,取出Session中的登錄用戶信息,如果信息為空,則為非法訪問,直接跳轉(zhuǎn)到登錄頁面,并提示相關(guān)信息:

//?取出login-user這個session User?loginUser?=?(User)req.getSession().getAttribute("loginUser"); if(loginUser?==?null){//?說明用戶沒有登錄,讓他跳轉(zhuǎn)到登錄頁面req.setAttribute("error",?"請登錄!");req.getRequestDispatcher("/LoginServlet").forward(req,res);return; }

那么這里就存在一個問題,一個網(wǎng)站會有很多個需要防止非法訪問的頁面,如果都是用這種方法豈不是很麻煩?

兩種解決辦法:

第一種:將這段驗證用戶的代碼封裝成函數(shù),每次調(diào)用

第二種:使用過濾器

4,利用Session防止表單重復(fù)提交

具體的做法:

在服務(wù)器端生成一個唯一的隨機標識號,專業(yè)術(shù)語稱為Token(令牌),同時在當前用戶的Session域中保存這個Token。然后將Token發(fā)送到客戶端的Form表單中,在Form表單中使用隱藏域來存儲這個Token,表單提交的時候連同這個Token一起提交到服務(wù)器端,然后在服務(wù)器端判斷客戶端提交上來的Token與服務(wù)器端生成的Token是否一致,如果不一致,那就是重復(fù)提交了,此時服務(wù)器端就可以不處理重復(fù)提交的表單。如果相同則處理表單提交,處理完后清除當前用戶的Session域中存儲的標識號。

在下列情況下,服務(wù)器程序?qū)⒕芙^處理用戶提交的表單請求:

1,存儲Session域中的Token(令牌)與表單提交的Token(令牌)不同。

2,當前用戶的Session中不存在Token(令牌)。

3,用戶提交的表單數(shù)據(jù)中沒有Token(令牌)。

例如:

創(chuàng)建FormTokenServlet,用于生成Token和跳轉(zhuǎn)到token.jsp頁面:

public?class?FormTokenServlet?extends?HttpServlet?{private?static?final?long?serialVersionUID?=?-8236507185410764108L;@Overrideprotected?void?doGet(HttpServletRequest?req,?HttpServletResponse?resp)?throws?ServletException,?IOException?{doPost(req,?resp);}@Overrideprotected?void?doPost(HttpServletRequest?req,?HttpServletResponse?resp)?throws?ServletException,?IOException?{//?創(chuàng)建令牌String?token?=?TokenProccessor.getInstance().makeToken();System.out.println("在FormServlet中生成的token:"?+?token);//?在服務(wù)器使用session保存token(令牌)req.getSession().setAttribute("token",?token);//?跳轉(zhuǎn)到token.jsp頁面req.getRequestDispatcher("/token.jsp").forward(req,?resp);} }

在token.jsp中使用隱藏域來存儲Token(令牌),提交Token(令牌)到服務(wù)器:

<%@?page?language="java"?contentType="text/html;?charset=UTF-8"pageEncoding="UTF-8"%> <%String?path?=?request.getContextPath();String?basePath?=?request.getScheme()?+?"://"+?request.getServerName()?+?":"?+?request.getServerPort()+?path?+?"/"; %> <html> <head> <base?href="<%=basePath%>"?/> <meta?http-equiv="Content-Type"?content="text/html;charset=UTF-8"> <title>表單提交</title> <link?href="css/bootstrap.css"?rel="stylesheet"> <script?src="js/jquery-3.2.1.js"></script> <script?src="js/bootstrap.js"></script> </head> <body><form?class="form-horizontal"?action="<%=request.getContextPath()%>/TokenServlet.html"?role="form"?method="post"><input?type="hidden"?name="token"?value="<%=session.getAttribute("token")?%>"><div?class="form-group"><label?for="firstname"?class="col-sm-1?control-label">用戶名</label><div?class="col-sm-3"><input?type="text"?class="form-control"?name="idCodeNum"placeholder="請輸入用戶名"></div></div><div?class="form-group"><div?class="col-sm-offset-1?col-sm-3"><button?type="submit"?class="btn?btn-default">提交</button><button?type="reset"?class="btn?btn-default">重置</button></div></div></form> </body> </html>

TokenServlet處理表單提交:

public?class?TokenServlet?extends?HttpServlet?{private?static?final?long?serialVersionUID?=?-8236507185410764108L;@Overrideprotected?void?doGet(HttpServletRequest?req,?HttpServletResponse?resp)?throws?ServletException,?IOException?{doPost(req,?resp);}@Overrideprotected?void?doPost(HttpServletRequest?req,?HttpServletResponse?resp)?throws?ServletException,?IOException?{boolean?b?=?false;String?client_token?=?req.getParameter("token");//?如果用戶提交的表單數(shù)據(jù)中沒有token,則用戶是重復(fù)提交了表單if?(client_token?==?null)?{b?=?true;}//?取出存儲在Session中的tokenString?serverToken?=?(String)?req.getSession().getAttribute("token");//?如果當前用戶的Session中不存在Token,則用戶是重復(fù)提交了表單if?(serverToken?==?null)?{b?=?true;}//?存儲在Session中的Token與表單提交的Token不同,則用戶是重復(fù)提交了表單if?(!client_token.equals(serverToken))?{b?=?true;}if?(b?==?true)?{System.out.println("請不要重復(fù)提交!");return;}//?移除session中的tokenreq.getSession().removeAttribute("token");System.out.println("正在處理用戶提交請求!!");} }

運行結(jié)果如下:

image

十、用戶禁用Cookie后的Session處理

這里存在一種情況,假如用戶瀏覽器禁用了Cookie怎么辦?比如我把Chrome的Cookie禁用,如下:

image

解決方法:URL重寫

Servlet中的response提供了對URL重寫的方法:

response.encodeRedirectURL(String url)用于對sendRedirect方法后的url地址進行重寫
response.encodeURL(String url)用于對表單action和超鏈接的url地址進行重寫

那么URL重寫是什么意思呢?其實就是人為地把JSESSIONID附在了url的后面,比如我們修改之前寫的簡易購物車,ShowBook中所有的點擊購買超鏈接都要重寫。

之前我們是這么寫的:

out.println("<tr><td>"+book.getName()+"</td><td><a?href='"+?req.getContextPath()?+"/BuyBookServlet.html?id="+book.getId()+"'>點擊購買</a></td></tr>");

現(xiàn)在進行URL重寫:

req.getSession(); String?url?=?"/MyCart/BuyBookCl?id="+book.getId(); url?=?resp.encodeURL(url); out.println("<tr><td>"+book.getName()+"</td><td><a?href='"+url+"'>點擊購買</a></td></tr>");

需要注意的是,重寫之前一定要調(diào)用或者確保使用過request.getSession()這個方法。

重寫之前,訪問ShowBookServlet的源代碼是這樣的:

image

重寫之后呢:

image

可以看到URL重寫之后,jsessionid這個參數(shù)自動附在了url后面,由此,得以確保我們的Session在Cookie被禁用的情況下繼續(xù)正常使用。這時候我們查看購物車的地址欄如下,可以明顯看到j(luò)sessionid這個參數(shù):

image

出處:

作者:Zender 原文:https://www.cnblogs.com/Zender/p/7657516.html

????覺得有用就轉(zhuǎn)發(fā)分享一下吧

1.?一文讀懂HttpServletRequest

2.?一文讀懂HttpServletResponse

3.?servlet就是這么簡單

4.?tomcat基本使用,就是這么簡單

附上熱門QQ群,存放資源和歷史資料,2000容量(低門檻付費群),長按二維碼入群

總結(jié)

以上是生活随笔為你收集整理的开发中经常碰到的问题cookie和session问题,今天一并解决的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲午夜久久久久久久久红桃 | 亚洲国产精品国自产拍av | 久操福利在线 | 国产美女视频网站 | 麻豆视频免费 | 成人网页 | 天天干夜夜干 | 欧美精品亚洲精品日韩精品 | 91香草视频 | 精品91自产拍在线观看二区 | 台湾swag在线观看 | 国产伦理在线观看 | 91视频大全 | 国产日韩视频在线观看 | javxxx| 看片网址国产福利av中文字幕 | 99精品视频播放 | 日韩精品一卡 | 亚洲最大成人网站 | www.四虎.| av大片免费看 | 久久桃花网 | 日韩男女视频 | 天堂网av中文字幕 | 国产三极片 | 奇米四色777 | 国产粉嫩白浆 | 美女隐私免费看 | 国产精品爽爽久久久久久 | 成人污 | 亚洲成年人免费观看 | 亚洲黄在线| 国内激情视频 | 亚洲性片 | 双性娇喘浑圆奶水h男男漫画 | 亚洲精品一区二区三区蜜桃 | 国产一区二区久久 | 精品免费一区二区 | 日韩精品视频网 | 337p亚洲精品色噜噜噜 | 国产一级免费av | 人人妻人人澡人人爽人人欧美一区 | 99re中文字幕| 丰满放荡岳乱妇91ww | 草av在线| 亚洲图片 自拍偷拍 | 色妞网| 日本大胆裸体做爰视频 | 99热欧美| 麻豆视频免费入口 | 午夜窝窝| 天天综合天天干 | 久久久久久九九 | 国产乱码久久久久久 | 欧美一区二区性久久久 | 国内少妇精品 | 在线视频 亚洲 | 精品一区二区三区视频在线观看 | 亚洲福利小视频 | 亚洲春色av| 老子影院午夜伦不卡大全 | 嫩草伊人久久精品少妇av | 精品人妻无码一区二区三区换脸 | 青青久久国产 | 波多野结衣中文在线 | 日韩精品免费观看 | 在线高清av | 老版k8经典电影 | 精品久久在线观看 | 在线看片你懂得 | 日韩中文字幕一区二区三区四区 | 日韩国产91| 成人激情在线观看 | 美女色诱男人激情视频 | 少妇人妻真实偷人精品视频 | 大地资源在线观看免费高清版粤语 | 四虎影视在线 | 91视频这里只有精品 | av亚洲在线 | 国产一区二区三区视频在线 | 青草视频免费看 | 精品丰满人妻无套内射 | 精品国产aⅴ一区二区三区四川人 | 日韩和欧美的一区二区 | 国产精品白嫩极品美女 | 四虎影城库 | 国语对白精彩对话 | 99久草| 国产极品在线观看 | 丰满少妇被猛烈进入无码 | 久草手机在线观看 | 成人a√ | 免费观看av网址 | 日韩性高潮 | 国产不卡在线观看 | 99亚洲国产精品 | 好吊色欧美一区二区三区视频 | 日韩欧美一卡 | 久久亚洲精精品中文字幕早川悠里 |