会话技术:Cookie、Session
目录
原理
常用API
注意问题
Session:服务器端会话技术
原理
常用API
注意
session的特点
概念
一次会话中包含多次请求和响应。 一次会话浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止。在一次会话的多次请求间,共享数据
cookie:客户端会话技术
原理
客户端第一次向服务器发出请求,服务器给出响应(包含响应头set-cookie=a)
客户端向服务器发出请求(此时包含请求头cookie=a)
常用API
- cookie cookie(String name, String value) 创建cookie对象
- response.addcookie(cookie cookie) 发送cookie对象
- cookie[] request.getcookies() 获取cookie,拿到数据
- setMaxAge(int seconds) 持久化存储
- 正数将cookie数据写到硬盘的文件中。持久化存储。并指定cookie存活时间,时间到后,cookie文件自动失效
- 负数默认值
- 零删除cookie信息
- 正数将cookie数据写到硬盘的文件中。持久化存储。并指定cookie存活时间,时间到后,cookie文件自动失效
- 负数默认值
- 零删除cookie信息
示例代码
//cookie1:添加cookie protected void doPost(HttpServletRequest request, HttpServletResponse response) thros ServletException, IOException { response.setContentType("text/html;charset=utf-8"); cookie cookie = ne cookie("name", "tom");//建立cookie对象 response.addcookie(cookie);//添加cookie } //cookie2:获取cookie protected void doPost(HttpServletRequest request, HttpServletResponse response) thros ServletException, IOException { response.setContentType("text/html;charset=utf-8"); cookie[] cookies = request.getcookies();//获取cookie的信息 for (cookie cookie : cookies) { System.out.println(cookie.getName()+":"+cookie.getValue()); } }
注意问题
一次可以发送多个cookie,可以创建多个cookie对象,使用response调用多次addcookie方法发送cookie即可
cookie在浏览器中保存多长时间?
- 默认情况下,当浏览器关闭后,cookie数据被销毁
- 持久化存储setMaxAge(int seconds)
cookie共享问题
假设在一个tomcat服务器中,部署了多个eb项目,那么在这些eb项目中cookie能不能共享?
- 默认情况下cookie不能共享
- setPath(String path):设置cookie的获取范围。默认情况下,设置当前的虚拟目录
- 如果要共享,则可以将path设置为"/"
不同的tomcat服务器间cookie共享问题?
setDomain(String path):如果设置一级域名相同,那么多个服务器之间cookie可以共享
- setDomain(".baidu."),那么tieba.baidu.和nes.baidu.中cookie可以共享
cookie的特点和作用
cookie存储数据在客户端浏览器
- 浏览器对于单个cookie 的大小有限制(4kb) 以及 对同一个域名下的总cookie数量也有限制(20个)
作用
- cookie一般用于存出少量的不太敏感的数据(数据不安全)
- 在不登录的情况下,完成服务器对客户端的身份识别
案例记录上一次登录时间
protected void doPost(HttpServletRequest request, HttpServletResponse response) thros ServletException, IOException { response.setContentType("text/html;charset=utf-8"); //先获取cookies cookie[] cookies = request.getcookies(); boolean flag=false;//是否有请求头last_time if(cookies.length>0&&cookies!=null){ for (cookie cookie : cookies) { if("lasttime".equals(cookie.getName())){ //如果条件成立,说明该用户之前登录过 String value = cookie.getValue();//获取日期数据 请求头cookie内的数据 value=URLDecoder.decode(value,"utf-8");//url解码 flag=true; Date date = ne Date(); SimpleDateFormat format = ne SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); String ne_date = format.format(date);//本次登录的时间字符串 ne_date=URLEncoder.encode(ne_date,"utf-8");//对字符串进行编码 cookie.setValue(ne_date); cookie.setMaxAge(6030); response.addcookie(cookie);//将其添加进浏览器 响应头set-cookie 内的数据 response.getWriter().println("上次登录时间"+value); } } } if (flag==false){//标志为false 表示登录 Date date = ne Date(); SimpleDateFormat format = ne SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); String ne_date = format.format(date); ne_date=URLEncoder.encode(ne_date,"utf-8"); cookie cookie = ne cookie("lasttime", ne_date); cookie.setMaxAge(6030); response.addcookie(cookie); response.getWriter().println("欢迎你登录!!!!!!"); } }
- URLDecoder.decode();URL解码
- URLEncoder.encode();URL编码
Session:服务器端会话技术 原理
客户端第一次发出请求(第一次获取session),服务器在内存中会创建一个新的Session对象,并且将响应头JSESSIONID传送到客户端浏览器中
客户端第二次发出请求,请求时会携带请求头JSESSIONID,也就确保了服务器在一次会话范围内,多次获取session对象是同一个
session的实现是依赖域cookie的
常用API- HttpSession session = request.getSession(); 获取Session
使用HttpSession对象
- Object getAttribute(String name)
- void setAttribute(String name, Object value)
- void removeAttribute(String name)
//session1 protected void doPost(HttpServletRequest request, HttpServletResponse response) thros ServletException, IOException { response.setContentType("text/html;charset=utf-8"); HttpSession session = request.getSession();//建立Session对象 session.setAttribute("name","Bob");//添加数据 } //session2 protected void doPost(HttpServletRequest request, HttpServletResponse response) thros ServletException, IOException { response.setContentType("text/html;charset=utf-8"); HttpSession session = request.getSession(); Object name = session.getAttribute("name");//获取数据 System.out.println(name); }
注意
当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
默认情况下。不是。
如果需要相同,则可以创建cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存。
protected void doPost(HttpServletRequest request, HttpServletResponse response) thros ServletException, IOException { response.setContentType("text/html;charset=utf-8"); HttpSession session = request.getSession(); cookie cookie = ne cookie("JSESSIONID", session.getId());//持久化请求头JSESSIonID cookie.setMaxAge(605); response.addcookie(cookie); System.out.println(session); }
客户端不关闭,服务器关闭后,两次获取的session是同一个吗?
不是同一个,要确保数据不丢失。tomcat自动完成以下工作
- session的钝化在服务器正常关闭之前,将session对象序列化到硬盘上
- session的活化在服务器启动后,将session文件转化为内存中的session对象即可
session什么时候被销毁
- 服务器关闭
- session对象调用invalidate() 。
- session默认失效时间 30分钟
session的特点
- session用于存储一次会话的多次请求的数据,存储在服务器端
- session可以存储任意类型,任意大小的数据(数据相较于cookie安全)
案例验证码
- 验证码字符串通过session进行存储
- 校验失败,跳转到登录页面,错误提示通过request进行存储
- 校验成功,重定向到成功页面,用户信息通过session进行存储
@WebServlet("/login") public class login extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) thros ServletException, IOException { response.setContentType("text/html;charset=utf-8"); request.setCharacterEncoding("utf-8"); //获取数据 String username = request.getParameter("username"); String passord = request.getParameter("passord"); String code = request.getParameter("code"); //判断语句 String session_code = (String) request.getSession().getAttribute("code"); if(code.equalsIgnoreCase(session_code)){ //验证码通过校验 if("tom".equals(username)&&"123".equals(passord)){ //用户密码验证成功 request.getSession().setAttribute("suess_name",username); response.sendRedirect("/test/suess.jsp"); }else { //用户名密码错误 request.setAttribute("error_1","用户名密码错误"); request.getRequestDispatcher("/login.jsp").forard(request,response); } }else { //验证码错误 request.setAttribute("error_2","验证码错误"); request.getRequestDispatcher("/login.jsp").forard(request,response); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) thros ServletException, IOException { doPost(request, response); } }
%@ page contentType="text/html;charset=UTF-8" language="java" %>登录页面 <%= request.getAttribute("error_1") != null ? request.getAttribute("error_1") : " "%> <%= request.getAttribute("error_2") != null ? request.getAttribute("error_2") : " "%>