cookie學習心得,基於java web專案的登入驗證
背景介紹:
1、cookie的由來:
web開發中,儲存web瀏覽狀態的一種方式,http請求是無狀態的, 當用戶在傳送一個請求關得到返回資訊之後,客戶端與伺服器端之間的網路連線就已經斷開了, 在下一個請求傳送時,伺服器無法確定這次請求和上次的請求是否來自同一個客戶端。
那時的辦法是在請求的頁面中插入一個token,並且在下一次請求中將這個token返回(至伺服器)。這就需要在form中插入一個包含token的隱藏表單域,或著在URL的qurey字串中傳遞該token。這兩種辦法都強調手工操作並且極易出錯。
這些方法的本質都是通過增加一種標記,來標識使用者通過瀏覽器的請求,進行使用者的標識。
2、cookie的應用:
最開始是為了購物車功能的實現,一般用來登入狀態的驗證和購物車之類的功能。
3、cookie的本質:
cookie是一個文字檔案,儲存在客戶端硬碟中(如果設定了cookie的過期時間),或者在使用者的瀏覽器記憶體中(如果cookie是臨時的)。
知識剖析
(一)建立cookie
cookie的建立,在登入成功之後建立,
cookie通常以 name=value格式的字串來使用,也就是key和value
.setMaxAge:cookie的生命週期,通過設定時間告知瀏覽器何時刪除該cookie
.setDomain:cookie的作用域,預設為建立該cookie的頁面所在的域名
.setPath:cookie的使用路徑,通過設定路徑確定哪一些請求的url,在其http請求的響應頭中加入該cookie資訊
(二)cookie的驗證方式
多數需要登入的站點通常會在你的認證資訊通過後來設定一個cookie,之後只要這個cookie存在並且合法,你就可以自由的瀏覽這個站點的所有部分。
在剛學習cookie時,對cookie的作用很模糊,所以對它的驗證方式不是很明白
也就是隻基於cookie的作用(記錄狀態),不涉及它的安全性,安全性是靠程式程式碼去實現的。也就是還有一個安全性,暫不討論。
我現在的理解:根據流程來講,
(1)客戶端輸入賬號、密碼登入傳送至伺服器端;
(2)伺服器端驗證,登入成功後,建立cookie,設定屬性;傳送至客戶端儲存
(3)瀏覽器在http請求頭中加入cookie資訊。傳送至伺服器端
(4)伺服器端進行驗證
兩點詳解
第4步中,伺服器端的驗證是指非空的驗證,即cookie是否存在--------非空
具體體現在下面的程式碼實戰中,設定的登入驗證攔截器起到的作用
第3步中,在http請求頭中加入cookie資訊之前,會進行合法性的驗證---------合法
主要在這一步的理解上,也就是cookie合法性的驗證,瀏覽器根據http請求的url和cookie的屬性進行比對,主要是其中的Domain、Path,
(1)Domain:瀏覽器會對domain的值與請求所要傳送至的域名,做一個尾部比較(即從字串的尾部開始比較),並且在匹配後傳送一個Cookie訊息頭。
簡單來說,cookie與域名相對應,要保證domain的值與請求的url中的域名相同,才會在請求頭中新增cookie;
(2)Path:通過將path屬性值與請求的URL從頭開始逐字串比較完成的。
簡化為,cookie與頁面對應,類似於一個攔截器,保證path的值與請求的url中的頁面路徑相同,才會在請求頭中新增cookie;
可以理解為,通過上面兩點,來達到只有“cookie中的地址”和“請求指向的地址”一致,該cookie才會新增到該請求上,來確保該cookie是由該程式建立的。
編碼實戰
主要就是cookie驗證登入的一個簡單的流程;
客戶端訪問伺服器,伺服器呼叫response.addCookie()方法,產生響應時,會產生set-cookie響應頭,將cookie文字傳送給客戶端,客戶端會將cookie文字儲存起來,當客戶端再次請求伺服器時,會產生cookie請求頭,將之前伺服器傳送的cookie資訊,再發送給伺服器,伺服器就可以根據cookie資訊跟蹤客戶端的狀態。
1、根據上面的流程,程式碼練習
(1)addCookie(),在使用者登入時,新增cookie,也就是controller中的登入
Cookie namecookie = new Cookie("name", people.getName());// 新建一個Cookie物件
namecookie.setMaxAge(30 * 60);// 設定為30min,生命週期
namecookie.setPath("/u");//設定Cookie的使用路徑
response.addCookie(namecookie);// 儲存cookie到客戶端
(2)登陸成功,客戶端儲存cookie
(3)通過攔截器,攔截url,實現一個設為使用者不登入可以訪問,一個設為使用者必須登入才可以訪問。
2、攔截器-------實現非空的驗證
通過實現HandleInterceptor介面,重寫裡面的方法;
重寫preHandle方法,返回的是true,繼續下面的方法;如果返回的是false,請求結束
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
Cookie[] cookies = request.getCookies();
if (cookies.length == 0) {
System.out.println("沒有cookie==============");
} else {
System.out.println("有cookie=========");
String name = "";
String password = "";
// 遍歷cookie如果找到登入狀態則返回true執行原來controller的方法
for (Cookie cookie : cookies) {
System.out.println(cookie.getValue());
if (cookie.getName().equals("name")) {
System.out.println("驗證成功" + cookie.getValue());
// 在頁面顯示登入使用者
name = cookie.getValue();
request.getSession().setAttribute("name", name);
System.out.println("---------------------" + name);
return true;
}
}
}
// 沒有找到登入狀態則重定向到登入頁,返回false,不執行原來controller的方法
response.sendRedirect("/test");
return false;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
springmvc配置檔案配置攔截器
<mvc:interceptors>
<!-- 配置登陸攔截器 -->
<mvc:interceptor>
<!--攔截後臺頁面的請求-->
<mvc:mapping path="/u/**"/>
<bean class="com.util.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
擴充套件思考
1、 Http是無狀態的短連線,而TCP是有狀態的長連線
Http協議(超文字傳輸協議),應用層
TCP協議(傳輸控制協議),傳輸層
Http就是在每次請求完成後就把TCP連線關了,所以是短連線。而我們直接通過Socket程式設計使用TCP協議的時候,因為我們自己可以通過程式碼區控制什麼時候開啟連線什麼時候關閉連線,只要我們不通過程式碼把連線關閉,這個連線就會在客戶端和服務端的程序中一直存在,相關狀態資料會一直儲存著。
參考文獻:
技能樹.IT修真院
“我們相信人人都可以成為一個工程師,現在開始,找個師兄,帶你入門,掌控自己學習的節奏,學習的路上不再迷茫”。
這裡是技能樹.IT修真院,成千上萬的師兄在這裡找到了自己的學習路線,學習透明化,成長可見化,師兄1對1免費指導,這裡的老大超級帥。快來與我一起學習吧~