【JavaWeb】Cookie与Session —— 状态管理技术

【JavaWeb】Cookie与Session —— 状态管理技术 一、Cookie1.1 Cookie概述Cookie是由服务器创建发送给客户端浏览器保存的一个键值对数据。当浏览器再次访问同一服务器时会自动携带之前保存的Cookie。工作原理Cookie的特点存储在客户端浏览器中由服务器创建浏览器自动携带数据量有限单个Cookie最大4KB安全性较低数据暴露在客户端可以设置过期时间1.2 Cookie的创建与发送服务器通过响应头Set-Cookie向浏览器发送Cookie// 方式1原始方式了解response.addHeader(Set-Cookie,usernamezhangsan);response.addHeader(Set-Cookie,age20);// 方式2便捷方式推荐Cookiecookie1newCookie(username,zhangsan);Cookiecookie2newCookie(age,20);response.addCookie(cookie1);response.addCookie(cookie2);响应头示例HTTP/1.1 200 OK Set-Cookie: usernamezhangsan Set-Cookie: age201.3 Cookie的获取浏览器再次请求时会自动在请求头中携带Cookie// 获取所有CookieCookie[]cookiesrequest.getCookies();if(cookies!null){for(Cookiecookie:cookies){Stringnamecookie.getName();// Cookie名称Stringvaluecookie.getValue();// Cookie值System.out.println(name value);}}请求头示例GET /index HTTP/1.1 Host: localhost:8080 Cookie: usernamezhangsan; age201.4 Cookie详解maxAgeCookie的生命周期maxAge决定了Cookie的存活时间以秒为单位maxAge值效果 0Cookie保存到硬盘存活指定秒数 0默认Cookie保存在浏览器内存关闭浏览器即消失 0立即删除该CookieCookiecookienewCookie(username,zhangsan);// 正数保存到硬盘7天有效cookie.setMaxAge(60*60*24*7);// 7天 604800秒// 负数保存在内存关闭浏览器消失默认cookie.setMaxAge(-1);// 0立即删除该Cookiecookie.setMaxAge(0);response.addCookie(cookie);pathCookie的访问路径path决定了浏览器在什么路径下会携带该Cookie规则说明浏览器访问路径包含Cookie的path携带该Cookie浏览器访问路径不包含Cookie的path不携带该Cookie示例// 假设项目名为 /day11_1CookieanewCookie(a,A);a.setPath(/day11_1/);// 访问 /day11_1/ 下的任意路径都携带CookiebnewCookie(b,B);b.setPath(/day11_1/jsps/);// 只有访问 /day11_1/jsps/ 下的路径才携带CookiecnewCookie(c,C);c.setPath(/day11_1/jsps/cookie/);// 只有访问 /day11_1/jsps/cookie/ 才携带访问路径携带的Cookie/day11_1/index.jspa/day11_1/jsps/a.jspa, b/day11_1/jsps/cookie/b.jspa, b, cpath默认值当前访问路径的父路径。例如访问/day11_1/jsps/a.jsp时创建的Cookie默认path为/day11_1/jsps/。domainCookie的域名domain用于实现跨二级域名共享Cookie// 设置domain为.baidu.com则以下域名共享该Cookie// www.baidu.com、zhidao.baidu.com、news.baidu.com、tieba.baidu.comCookiecookienewCookie(token,abc123);cookie.setDomain(.baidu.com);// 注意前面的点cookie.setPath(/);// 路径设为根response.addCookie(cookie);1.5 Cookie使用示例记住用户名登录页面login.jsp% page contentTypetext/html;charsetUTF-8 languagejava % html headtitle登录/title/head body h2用户登录/h2 form action/day11_1/login methodpost 用户名input typetext nameusername value${cookie.username.value} /br/ 密码input typepassword namepassword /br/ input typecheckbox nameremember valuetrue / 记住用户名br/ input typesubmit value登录 / /form /body /html登录ServletWebServlet(/login)publicclassLoginServletextendsHttpServlet{protectedvoiddoPost(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{req.setCharacterEncoding(UTF-8);Stringusernamereq.getParameter(username);Stringpasswordreq.getParameter(password);Stringrememberreq.getParameter(remember);if(admin.equals(username)123456.equals(password)){// 判断是否勾选记住用户名if(true.equals(remember)){// 创建Cookie保存7天CookiecookienewCookie(username,username);cookie.setMaxAge(60*60*24*7);// 7天cookie.setPath(/);resp.addCookie(cookie);}else{// 删除CookieCookiecookienewCookie(username,);cookie.setMaxAge(0);// 立即删除cookie.setPath(/);resp.addCookie(cookie);}resp.sendRedirect(/day11_1/home.jsp);}else{resp.sendRedirect(/day11_1/login.jsp);}}}二、Session2.1 Session概述Session会话是服务器端的状态管理技术。服务器为每个客户端创建一个Session对象用于保存用户的状态信息。Session的特点存储在服务器端安全性高可以存储任意类型的数据Object数据量理论上无限制受服务器内存限制依赖Cookie传递Session ID默认Session是Servlet三大域对象之一域对象作用范围创建时机销毁时机request一次请求请求开始时请求结束时session一次会话第一次调用getSession()超时或调用invalidate()application(ServletContext)整个Web应用服务器启动服务器关闭2.2 Session的创建与获取// 获取Session如果不存在则创建新的HttpSessionsessionrequest.getSession();// 获取Session如果不存在则返回null不创建新的HttpSessionsessionrequest.getSession(false);// 获取Session如果不存在则创建新的与request.getSession()等价HttpSessionsessionrequest.getSession(true);JSP中直接使用% // JSP内置了session对象无需创建 session.setAttribute(username, 张三); String name (String) session.getAttribute(username); %2.3 Session域对象方法方法说明setAttribute(String name, Object value)存储数据到Session域getAttribute(String name)从Session域获取数据removeAttribute(String name)从Session域删除数据getId()获取Session IDinvalidate()使Session失效注销登录isNew()判断Session是否是新创建的getMaxInactiveInterval()获取最大不活动时间秒setMaxInactiveInterval(int interval)设置最大不活动时间// 存储数据session.setAttribute(user,newUser(张三,20));session.setAttribute(cart,newShoppingCart());// 获取数据Useruser(User)session.getAttribute(user);// 删除数据session.removeAttribute(user);// 使Session失效退出登录session.invalidate();2.4 Session原理Session的实现依赖于Cookie第一次请求 浏览器 → 请求服务器 → 服务器调用getSession()创建Session → 生成JSESSIONID → 通过Cookie响应给浏览器 → Set-Cookie: JSESSIONIDxxxxxx 第二次请求 浏览器 → 请求服务器携带Cookie: JSESSIONIDxxxxxx → 服务器根据JSESSIONID找到对应的Session对象 → 使用同一个SessionSession工作原理图┌─────────────┐ ┌─────────────┐ │ 浏览器 │ ← JSESSIONID Cookie │ 服务器 │ │ (客户端) │ ─────────────────→ │ (Session池) │ │ │ │ │ │ JSESSIONID │ │ MapString,│ │ abc123 │ ← 查找Session ───→ │ HttpSession│ │ │ │ abc123 → │ └─────────────┘ │ Session对象 │ └─────────────┘关键点服务器通过JSESSIONID这个Cookie来识别客户端JSESSIONID的maxAge默认为-1浏览器内存中关闭即消失如果浏览器禁用了CookieSession将无法正常工作需要使用URL重写2.5 Session的生命周期创建时机Session在第一次调用request.getSession()时创建不是服务器启动就创建。销毁时机情况说明超时超过最大不活动时间默认30分钟Tomcat自动销毁主动销毁调用session.invalidate()方法服务器关闭服务器正常关闭时Session会被序列化到硬盘配置Session超时时间方式1web.xml配置全局生效session-config!-- 单位为分钟默认30分钟 --session-timeout30/session-timeout/session-config方式2代码设置单个Session生效// 设置Session 10分钟不活动则失效session.setMaxInactiveInterval(60*10);// 600秒 10分钟2.6 Session使用示例登录状态保持登录ServletWebServlet(/login)publicclassLoginServletextendsHttpServlet{protectedvoiddoPost(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{req.setCharacterEncoding(UTF-8);Stringusernamereq.getParameter(username);Stringpasswordreq.getParameter(password);// 验证登录if(admin.equals(username)123456.equals(password)){// 登录成功将用户信息存入SessionHttpSessionsessionreq.getSession();session.setAttribute(user,newUser(username,adminqq.com));resp.sendRedirect(/day11_1/home.jsp);}else{req.setAttribute(error,用户名或密码错误);req.getRequestDispatcher(/login.jsp).forward(req,resp);}}}首页home.jsp% page contentTypetext/html;charsetUTF-8 languagejava % html headtitle首页/title/head body h1欢迎来到首页/h1 %-- 从Session获取用户信息 --% % User user (User) session.getAttribute(user); % % if (user ! null) { % p当前用户% user.getUsername() %/p p邮箱% user.getEmail() %/p a href/day11_1/logout退出登录/a % } else { % p您还未登录a href/day11_1/login.jsp请登录/a/p % } % /body /html退出登录ServletWebServlet(/logout)publicclassLogoutServletextendsHttpServlet{protectedvoiddoGet(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{// 获取Session并使其失效HttpSessionsessionreq.getSession(false);if(session!null){session.invalidate();// 销毁Session}resp.sendRedirect(/day11_1/login.jsp);}}三、Cookie vs Session 对比对比项CookieSession存储位置客户端浏览器服务器端安全性低数据暴露给用户高数据在服务器存储类型只能存字符串可以存任意Object存储大小单个最大4KB理论上无限制数量限制一个站点最多20个无限制生命周期可设置长期保存默认30分钟不活动销毁实现依赖无依赖Cookie传递JSESSIONID性能影响每次请求携带增加流量占用服务器内存典型用途记住用户名、购物车未登录登录状态、用户权限信息四、URL重写如果用户浏览器禁用了CookieSession将无法通过Cookie传递JSESSIONID。此时可以使用URL重写技术。原理将JSESSIONID直接附加在URL后面。// 对URL进行编码智能添加JSESSIONIDStringurlresponse.encodeURL(/day11_1/home.jsp);// 结果/day11_1/home.jsp;jsessionidxxxxxxxx// 重定向URL编码StringredirectUrlresponse.encodeRedirectURL(/day11_1/login.jsp);使用场景浏览器支持Cookie时encodeURL()不会在URL后追加JSESSIONID浏览器不支持Cookie时encodeURL()会自动在URL后追加JSESSIONID%-- 使用encodeURL确保Session正常工作 --% a href%response.encodeURL(/day11_1/home.jsp)%首页/a a href%response.encodeURL(/day11_1/cart.jsp)%购物车/a实际开发中URL重写很少使用通常要求用户开启Cookie支持。五、综合案例完整的登录状态管理5.1 登录页面login.jsp% page contentTypetext/html;charsetUTF-8 languagejava % html headtitle登录/title/head body h2用户登录/h2 form action/day11_1/login methodpost 用户名input typetext nameusername value${cookie.rememberUser.value} /br/ 密码input typepassword namepassword /br/ input typecheckbox nameremember valuetrue ${not empty cookie.rememberUser ? checked : }/ 记住用户名br/ input typesubmit value登录 / /form p stylecolor:red${requestScope.error}/p /body /html5.2 登录ServletWebServlet(/login)publicclassLoginServletextendsHttpServlet{protectedvoiddoPost(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{req.setCharacterEncoding(UTF-8);Stringusernamereq.getParameter(username);Stringpasswordreq.getParameter(password);Stringrememberreq.getParameter(remember);// 验证实际应从数据库查询if(admin.equals(username)123456.equals(password)){// 1. Session保存登录状态HttpSessionsessionreq.getSession();session.setAttribute(user,newUser(username,adminqq.com));// 2. Cookie记住用户名CookiecookienewCookie(rememberUser,username);if(true.equals(remember)){cookie.setMaxAge(60*60*24*7);// 7天}else{cookie.setMaxAge(0);// 删除}cookie.setPath(/);resp.addCookie(cookie);resp.sendRedirect(/day11_1/home.jsp);}else{req.setAttribute(error,用户名或密码错误);req.getRequestDispatcher(/login.jsp).forward(req,resp);}}}5.3 登录过滤器防止未登录访问WebFilter(/*)publicclassLoginFilterimplementsFilter{publicvoiddoFilter(ServletRequestreq,ServletResponseresp,FilterChainchain)throwsIOException,ServletException{HttpServletRequestrequest(HttpServletRequest)req;HttpServletResponseresponse(HttpServletResponse)resp;Stringurirequest.getRequestURI();// 放行登录相关资源if(uri.contains(login)||uri.contains(register)||uri.contains(.css)||uri.contains(.js)){chain.doFilter(req,resp);return;}// 检查SessionHttpSessionsessionrequest.getSession(false);if(session!nullsession.getAttribute(user)!null){chain.doFilter(req,resp);// 已登录放行}else{response.sendRedirect(/day11_1/login.jsp);// 未登录跳转登录页}}}本章小结知识点核心内容Cookie服务器创建、客户端保存的键值对用于状态保持Cookie创建new Cookie(name, value)response.addCookie()Cookie获取request.getCookies()maxAge0硬盘保存、0内存保存默认、0立即删除path决定浏览器在什么路径下携带CookieSession服务器端会话对象存储用户状态Session获取request.getSession()Session原理依赖JSESSIONID Cookie识别客户端Session生命周期默认30分钟不活动销毁可调invalidate()主动销毁Cookie vs SessionCookie在客户端、存字符串、4KB限制Session在服务器、存对象、更安全URL重写Cookie禁用时通过URL传递JSESSIONID如果本文对你有帮助欢迎点赞 、收藏 ⭐、关注专栏有问题欢迎在评论区交流讨论。