Cookie和Session實現儲存登入狀態免登入。
首先Cookie和Session都是為了狀態管理,HTTP協議是無狀態的,不能儲存每次提交的資訊,即當伺服器返回與請求相對應的應答之後,這次事務的所有資訊就丟掉了。 如果使用者發來一個新的請求,伺服器無法知道它是否與上次的請求有聯絡。 對於那些需要多次提交資料才能完成的Web操作,比如登入來說,就成問題了。所以需要狀態管理也就是通過Cookie和Session。
一.Cookie
1. 什麼是Cookie? 用我的理解來說,瀏覽器A在第一次請求伺服器B的時候,伺服器B會為該瀏覽器A建立一個Cookie,並在響應時候把這個Cookie一同返回給瀏覽器A,這樣A在請求資料不變的情況下再次
2. Cookie持續多久呢? 可以通過setMaxAge()方法設定Cookie存在時間。 取值說明:
0有效期,單位秒 =0失效 <0記憶體儲存
二.Session 1. 什麼是Session 我的理解,Session是為了給瀏覽器在伺服器端儲存自己獨有資料的一個集合,只是在伺服器端。通過setAttribute()方法存資料,getAttribute()方法取資料。
2.Session持續多久呢?
預設不設定的話保持30分鐘。 有兩種設定Session的方法: (1)setMaxInactiveInterval()方法,單位秒 (2)在web.xml中配置 ,單位分鐘
<session-config>
<session-timeout>20</session-timeout>
</session-config>
三.使用者登陸過程中的cookie和session保持過程 假設沒有設定其他cookie情況下,A在第一次訪問B時,B會為A建立一個屬於A的session,並在B響應A時通過cookie儲存sessionid響應給A。這樣A在第二次訪問B的時候,A帶著cookie(此時裡面有sessionid)請求B,B收到請求後會通過cookie的sessionid辨識出屬於A的session,這就是整個過程。
四.Cookie和Session實現使用者登入儲存使用者登入狀態一定時間免登陸。
1.設計思路: 首先,使用者登入成功後儲存使用者登陸的使用者名稱到Cookie,同時設定Cookie的有效時間,在下次使用者想免輸入登陸時,直接判斷Cookie是否含有該使用者的使用者名稱,如果有則直接登陸不需要輸入,否則需要重新輸入使用者名稱和密碼。 2.程式碼實現: 為了大家看著方便,我儘可能把所有servlet分開寫了。 (1)KeepLoginServlet(使用者登入)
@WebServlet("/keeploginservlet")
public class KeepLoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public KeepLoginServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
// 從session中獲取驗證碼
String vcode = (String) session.getAttribute("vcode");
String username = request.getParameter("username");
String password = request.getParameter("password");
String code = request.getParameter("code");
PrintWriter out = response.getWriter();
// System.out.println("輸入的code:"+code);
// System.out.println("生成的vcode:"+vcode);
if (!vcode.equals(code)) {
out.write("<html>"
+ "<head><script type='text/javascript'> alert('驗證碼錯誤!');location='login.html';</script></head>"
+ "<body></body></html>");
return; // 不繼續執行,重新返回login.html頁面
}
if ("123".equals(username)) {
if ("123".equals(password)) {
// 建立cookie並將成功登陸的使用者儲存在裡面
Cookie cookie = new Cookie("username", username);
cookie.setMaxAge(60); // 設定一分鐘有效
response.addCookie(cookie); // 伺服器返回給瀏覽器cookie以便下次判斷
response.sendRedirect(request.getContextPath() + "/index.html"); // 重定向到index.html
} else {
out.write("<html>"
+ "<head><script type='text/javascript'> alert('密碼錯誤!');location='login.html';</script></head>"
+ "<body></body></html>");
return;
}
} else {
out.write("<html>"
+ "<head><script type='text/javascript'> alert('不存在該使用者!');location='login.html';</script></head>"
+ "<body></body></html>");
return;
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
在這判斷使用者輸入是否正確,因為是測試,所以使用者名稱和密碼寫死都是123,驗證碼是一個工具類下面會給出程式碼,如果使用者登入成功則將這個使用者儲存到Cookie裡,設定過期時間為1分鐘,以便下次免登陸。
(2)KeepLoginServlet(驗證碼) 這裡為了節省空間直接給出doGet方法,這裡有一個驗證碼的jar包ValidateCode .jar非常方便大家可以自行查詢。地址是(@WebServlet(“/vcodeservlet”))
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
//建立驗證碼圖片流
ValidateCode validateCode = new ValidateCode(120,50,4,20);
validateCode.write(response.getOutputStream());
//將驗證碼存入session中
session.setAttribute("vcode", validateCode.getCode());
}
(3)FindCookieServlet(判斷使用者是否可以免登陸) 這裡是實現的邏輯是:遍歷所有cookie看是否含有username,如果含有username說明使用者登陸過,可以免輸入直接登陸。地址是(@WebServlet(“/dindcookieservlet”))
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
boolean flag = false;
PrintWriter out = response.getWriter();
// 判斷cookie是否有username,如果有代表登陸過
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
System.out.println(URLDecoder.decode(cookie.getName(), "utf-8"));
if (URLDecoder.decode(cookie.getName(), "utf-8").equals("username")) { // 表明已經登陸過了,就直接跳轉了
flag = true;
}
}
}
if(flag) {
response.sendRedirect(request.getContextPath() + "/index.html");
}else {
out.write("<html>"
+ "<head><script type='text/javascript'> alert('沒有登陸過,請登入!');location='login.html';</script></head>"
+ "<body></body></html>");
}
}
(4)ReturnClearCookie(清除使用者儲存的cookie) Cookie是沒有直接刪除指定cookie的方法的,所以我可以找到cookie裡的username並把他的有效時間設定成0秒,這樣間接實現了刪除Cookie裡的username。地址是(@WebServlet(“/returnclearcookie”))。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//這裡就是把username的cookie設定成0秒有效期,就是直接刪除掉了
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
System.out.println(URLDecoder.decode(cookie.getName(), "utf-8"));
if (URLDecoder.decode(cookie.getName(), "utf-8").equals("username")) { // 表明已經登陸過了,就直接跳轉了
cookie.setMaxAge(0);
response.addCookie(cookie);
}
}
}
response.sendRedirect(request.getContextPath()+"/login.html");
}
(5)兩個頁面 login.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登入頁面</title>
<style type="text/css">
.dv_error {
color: red;
}
</style>
</head>
<body>
<form action="/myday13_zhuangtaiguanli/keeploginservlet" method="post">
<label>賬號:</label><input type="text" id="username" name="username"><br />
<label>密碼:</label><input type="password" id="password" name="password"><br />
<label>密碼:</label><input type="text" id="code" name="code"><img id="img1" src="/myday13_zhuangtaiguanli/vcodeservlet" onclick="changeImg()" /><a href="javascript:void(0)" onclick="changeImg()">看不清換一張</a><br />
<input type="button" onclick="check()" value="登入">
<label><a href="/myday13_zhuangtaiguanli/dindcookieservlet" >已經登陸,直接登陸</a></label>
</form>
<script type="text/javascript">
function check(){
var username = document.getElementById("username")
var password = document.getElementById("password")
var code = document.getElementById("code")
if(username.value == ""){
alert("請輸入使用者名稱")
}else if(password.value == ""){
alert("請輸入密碼")
}else if(code.value == ""){
alert("請輸入驗證碼");
}else{
document.forms[0].submit()
}
}
function changeImg(){
var img1 = document.getElementById("img1")
img1.src="/myday13_zhuangtaiguanli/vcodeservlet?num"+Math.random();
}
</script>
</body>
</html>
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>歡迎登入...</h1>
<a href="/myday13_zhuangtaiguanli/returnclearcookie">退出登陸並不保留登陸資訊</a><br/>
<a href="login.html">退出登入,但5分鐘內免登陸</a>
</body>
</html>
五.測試結果 這是第一次登陸成功結果,通過開發者工具可以清楚看到,Cookie儲存了username,以便下次判斷。
這是免登陸的結果截圖,可以清楚看到,Cookie裡是有username的,所以可以直接跳轉進來。
這是點選清除Cookie退出或Cookie過期時,點選免輸入的結果,細心觀察可以看到,此時Cookie已經沒有username了,並且sessionid是沒有變的。所以是登陸不進去需要重新輸入的。
六.總結 在Servlet裡Cookie和Session是一個非常重要的概念,熟悉Cookie和Session的過程和應用場景是非常必要的,也要了解兩者的關係。 一口氣寫完,想必有多處不足和失誤,歡迎提出疑惑。也歡迎大家隨時溝通交流。