Session 優化登錄案例
1.代碼實現
public class LoginServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//設置請求編碼格式
request.setCharacterEncoding("utf-8");
//設置響應編碼格式
response.setContentType("text/html;charset=utf-8");
//獲取session中的數據
HttpSession session=request.getSession();
String str=((String) session.getAttribute("flag")==null?" ":"用戶名或密碼錯誤");
session.invalidate();
//獲取請求信息
//處理請求信息
//響應處理結果
//直接響應
response.getWriter().write("<html>");
response.getWriter().write("<head>");
response.getWriter().write("</head>");
response.getWriter().write("<body>");
response.getWriter().write("<form action='user' method='get' />");
response.getWriter().write("<font>"+str+"</font>");
response.getWriter().write("用戶名:<input type='text'name='uname'value=''/><br />");
response.getWriter().write("密碼:<input type='password'name='pwd'value=''/><br />");
response.getWriter().write("<input type='submit' value='登錄'/><br />");
response.getWriter().write("</form>");
response.getWriter().write("</body>");
response.getWriter().write("</html>");
}
}
public class UserServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//設置請求編碼格式
request.setCharacterEncoding("utf-8");
//設置響應編碼格式
response.setContentType("text/html;charset=utf-8");
//獲取請求信息
String uname=request.getParameter("uname");
String pwd=request.getParameter("pwd");
//處理請求信息
if("zhangsan".equals(uname)&&"123".equals(pwd)) {
//登錄成功
}else {
//登錄失敗
//獲取session對象
HttpSession session=request.getSession();
session.setAttribute("flag","false");
//響應處理結果(重定向到login)
response.sendRedirect("login");
}
}
}
2.過程闡述
在登錄失敗的操作中 使用session技術設置了flag標誌 將其保存到session對象中 而重定向到login時 通過session對象拿到標誌 從而可以提示用戶名或密碼錯誤 完成需求
3.具體細節分析
當我們第一次訪問login時 可以在響應頭中看到有一個Set-Cookie,這個cookie攜帶了第一次的session對象 但馬上session對象就被銷燬 接着進入登錄步驟
這時我們輸入錯誤的用戶名和密碼 瀏覽器首先向/user發起一個請求,這個請求的請求頭中攜帶了剛剛被銷燬的session的ID,隨即我們在響應頭中看到這是服務器有給我們了一個新的Set-Cookie,即有新創建了一個session對象 這個session對象中寫入了flag信息(用戶名或密碼錯誤的信息)這時可能會產生一個疑問 明顯請求中已經拿到了一個session-ID 爲什麼有創建了一個session對象 這時因爲該session對象已經被銷燬了 就算有session-ID也會重新創建一個session
這時 我們來看login這個重定向請求 可以看到這個請求的請求頭中拿到了一個session 並且這個session-ID和上一個響應頭中的session-ID一樣 說明這是同一個session對象 那麼他們所保存的flag標記信息就是一樣的 這樣就可以完成我們對於用戶名或密碼錯誤的提示需求 完成之後 我們銷燬了session對象
4.bug記錄
我們試着不對session進行銷燬 就會發現以下的問題 在每一次刷新login時 都會提示用戶名或密碼錯誤 如圖
原因是如果不對session對象進行銷燬 在瀏覽器不關閉 session對象不失效的情況下 用戶的任意請求獲取的都是同一個session對象 那麼就會一直提示這句話 在用戶正常刷新之後 也會出現如上的錯誤情況 造成功能的錯誤
5.總結
1.瀏覽器發起請求到ServletA 在ServletA中獲取到session對象 如果此次請求中沒有session-ID就創建一個session對象 如果有session-ID就將其對應的session對象返回(前提是該session對象沒有到期銷燬 如果session對象銷燬了 就算有session-ID也會重新創建一個session對象 上面的過程就是這樣的體現)
2.session的作用域:在瀏覽器不關閉且session不失效的情況下 同一用戶的任意請求都獲取的是一個session