思路
使用cookie存儲賬號、密碼,使用Filter攔截,從cookie中取出賬號、密碼。若用戶要注銷|登出、不再想使用自動登錄,將cookie的有效期設置為0即可。
瀏覽器可以查看Cookie,不能直接存儲賬號、密碼的明文,使用Cookie存儲賬號、密碼時需要加密,從Cookie中取出來時需要解密。
每次HTTP請求都使用Filter攔截,從Cookie中解密出賬號、密碼,每次都要解密,浪費時間。第一次從Cookie中解密出賬號、密碼后,可以將賬號、密碼放到session域中,會話期間直接從session中取,不必再解密。
登錄頁面
<form action="loginServlet" method="post"> 用戶名:<input type="text" name="user" /><br /> 密碼:<input type="password" name="pwd" /><br /> <button type="submit">登錄</button><br /> ${requestScope.errorMsg} </form>
EL表達式沒有空指針異常,沒有時返回空串。所以沒有errorMsg時, ${requestScope.errorMsg} 也不會出錯。
EL表達式不同於<% %>、<%= %>,EL表達式不會報數組越界、域中沒有這個變量(空指針異常)這些錯,找不到就返回空串,不會報錯。但EL表達式中不能使用+號來拼接字符串。
將登錄頁面設為項目初始頁面
<welcome-file-list> <welcome-file>/login.jsp</welcome-file> </welcome-file-list>
處理登錄表單的Servlet
1 @WebServlet("/loginServlet") 2 public class LoginServlet extends HttpServlet { 3 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 4 String user=request.getParameter("user"); 5 String pwd=request.getParameter("pwd"); 6 7 //連接數據庫,檢查是否正確 8 //...... 9 if (true){ 10 //放到session中 11 HttpSession session = request.getSession(); 12 session.setAttribute("user",user); 13 session.setAttribute("pwd","pwd"); 14 15 //將值加密后存儲在Cookie中,此處略過加密 16 Cookie cookie=new Cookie("autoLogin",user+"-"+pwd); 17 //整個項目中可用 18 cookie.setPath(request.getContextPath()); 19 //這個域名地址下的所有webApp都可用 20 //cookie.setPath("/"); 21 cookie.setMaxAge(60*60*24*7); 22 response.addCookie(cookie); 23 24 //重定向到目標頁面。request.getContextPath()獲取的是當前web應用的根目錄 25 response.sendRedirect(request.getContextPath()+"/index.jsp"); 26 //不能這樣寫,這樣寫表示域名下的index.jsp,不是域名/web應用/index.jsp。 27 //response.sendRedirect("/index.jsp"); 28 } 29 else{ 30 //轉發到登錄頁面,附加錯誤信息 31 request.setAttribute("errorMsg","賬戶名或密碼錯誤"); 32 request.getRequestDispatcher("/login.jsp").forward(request,response); 33 } 34 35 } 36 37 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 38 doPost(request,response); 39 } 40 }
首頁
<h2>hello,${sessionScope.user}</h2>
Filter實現自動登錄
1 @WebFilter("/*") 2 public class HandlerFilter implements Filter { 3 public void destroy() { 4 } 5 6 public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { 7 //統一全站編碼 8 req.setCharacterEncoding("utf-8"); 9 resp.setContentType("text/html;charset=utf-8"); 10 11 //ServletRequest不能獲取session、cookie,需要強轉為HttpServletRequest 12 HttpServletRequest httpReq = (HttpServletRequest) req; 13 14 //檢查session中有沒有用戶信息 15 HttpSession session = httpReq.getSession(); 16 if (session.getAttribute("user")==null){ 17 //如果session中沒有,從Cookie中找autoLogin。可能是會話結束后再次訪問,比如離開網站30min(session默認超時時間)后再次訪問、關閉瀏覽器后重新打開再次訪問。 18 Cookie[] cookies = httpReq.getCookies(); 19 //需要先檢測cookies是否為null,為null時會報空指針異常 20 if (cookies!=null){ 21 for (Cookie cookie:cookies){ 22 if (cookie.getName().equals("autoLogin")) { 23 //需要先解密,此處略過 24 //...... 25 String[] userInfo=cookie.getValue().split("-"); 26 session.setAttribute("user",userInfo[0]); 27 session.setAttribute("pwd",userInfo[1]); 28 } 29 } 30 } 31 } 32 33 chain.doFilter(req, resp); 34 } 35 36 public void init(FilterConfig config) throws ServletException { 37 38 } 39 40 }
ServletRequest不能獲取session、cookie,需要強轉為HttpServletRequest才可以。
處理注銷 | 登出 | 不再使用自動登錄 的Servlet
1 @WebServlet("/logoutServlet") 2 public class LogoutServlet extends HttpServlet { 3 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 4 //從session中移出用戶信息 5 HttpSession session = request.getSession(); 6 session.removeAttribute("user"); 7 session.removeAttribute("pwd"); 8 9 //刪除Cookie,此處采用同名覆蓋,也可以遍歷獲取,再將有效期設為0 10 Cookie cookie=new Cookie("autoLogin",""); 11 cookie.setPath(request.getContextPath()); 12 cookie.setMaxAge(0); 13 response.addCookie(cookie); 14 } 15 16 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 17 doPost(request,response); 18 } 19 }
獲取當前WebApp的根目錄:
String path1 = request.getContextPath(); //通過request對象來獲取
String path2 = getServletContext().getContextPath(); //通過ServletContext對象來獲取
這2種方式獲取的都是相對路徑。
獲取當前WebApp中的某個資源在服務器上的絕對路徑:
String path3 = getServletContext().getRealPath("/index.jsp"); //通過ServletContext對象來獲取
就是把當前項目的根目錄(絕對路徑)、參數中的路徑拼接在一起。