Cookie和Session

Cookie和Session

会话:从用户打开浏览器,访问一个web应用程序开始,多次点击、访问服务器上的资源,多次的请求和响应,直到关闭浏览器,这整个过程就是一个会话

我们知道Http是一个无状态的协议,服务器不会记录客户端的信息,不管第几次发送请求给服务器,它也不会认识你

为了可以让浏览器和服务器进行一些交互,保存住一些必要数据,在HttpServlet中,提供了两个用于保存会话中数据的两个对象,分别是Cookie和Session

会话实现的过程:

浏览器访问服务器资源,建立会话,产生一个会话对象(Session),并且为这个会话生成一个唯一的标识,服务器会把这个标识响应给浏览器,保存在浏览器中。下次浏览器请求服务器时会带上这个标识,此时服务器会根据这个标识查找对应的Session对象,如果找到,那么就是同一个会话,继续本次会话,如果没找到,此时会再创建一个新的会话,生成新的标识。

Cookie

Cookie浏览器端的会话技术,将服务器返回的小量数据保存在浏览器中。

应用场景

  • 网站登录时的记住密码和自动登录,当我们清除浏览器中的Cookie时,可以发现访问网站时还需要重新登录该网站
  • 保存一些上次登录时间、上次打开的网页等等
  • 记录浏览的次数···

使用Cookie主要用来做客户端和服务器之间的状态的保持(保持一种交互的状态),对于安全性要求不高,不需要浏览器存储大量的数据

使用

发送Cookie
  • 创建Cookie对象,直接new Cookie(String key,String value);
  • 将Cookie数据保存到客户端,使用response对象的addCookie()方法
        Cookie cookie = new Cookie("name","xiaoming");
        resp.addCookie(cookie);

打开浏览器的开发者工具,访问该Servlet,查看该请求;

在这里插入图片描述

获取Cookie
  • 获取浏览器请求中的Cookie,使用request对象的getCookies()方法
  • 遍历获取所有Cookie的键值对信息
        Cookie[] cookies = req.getCookies();
        for (Cookie c : cookies){
            String key = c.getName();//获取Cookie对象中的键
            String value = c.getValue();//获取Cookie对象中的值
            System.out.println(key+"="+value);
        }

(获取Cookie的前提是浏览器存储了Cookie,如果浏览器禁用了Cookie,我们也就获得不到Cookie,会话也因此失效)

编码问题

Cookie传递的数据从Tomcat8开始支持中文,但是我们也不建议使用中文

需要使用中文的话,建议将中文进行编码,查看时在进行解码

API:

  • URLEncode类:
    • public static String encode(String s, String enc);将指定字符串s使用指定的规则enc进行编码
  • URLDecode类:
    • public static String decode(String s, String enc);将指定字符串s使用指定的规则enc进行解码
        String encode = URLEncoder.encode("小明","utf-8");
        Cookie cookie = new Cookie("name",encode);
        resp.addCookie(cookie);


        Cookie[] cookies = req.getCookies();
        for (Cookie c : cookies){
            String key = c.getName();
            String value = URLDecoder.decode(c.getValue(),"utf-8");
            System.out.println(key+"="+value);
        }

在这里插入图片描述

配置Cookie

在发送请求时,Cookie会放在请求头中传给服务器,但是一个浏览器中保存着很多个网站的Cookie,总不能将所有的Cookie都发送过去,所以,每一个Cookie都有一个自己的有效路径,只有访问到这个Cookie的有效路径,那么请求头中才会携带响应的Cookie

在Cookie对象中,有几个方法可以对Cookie进行响应的配置

返回值方法名说明
voidsetPath(String url)设置Cookie的有效路径
voidsetMaxAge(int expiry)设置Cookie的存活时间(秒)
Cookie的有效路径
cookie.setPath();
Cookie的最大存活时间
cookie.setMaxAge(60);
删除已有的Cookie

将一个Cookie存活时间设置为0,就可以达到效果

创建一个新的Cookie,设置key和有效路径都要和需要删除的Cookie的key和有效路径相同,设置存活时间为0,覆盖旧的Cookie即可

        Cookie cookie1 = new Cookie("name","xxx");
        cookie1.setMaxAge(0);
        resp.addCookie(cookie1);
示例:

获取上次访问时间

@WebServlet(value = {"/cookieTest"})
public class CookieDemo2  extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        Cookie[] cookies = req.getCookies();
        String lasttime = null;
        for (int i=0;cookies!=null && i<cookies.length;i++){
            if (cookies[i].getName().equals("lastDate")){
                lasttime = URLDecoder.decode(cookies[i].getValue(),"utf-8");
                out.print("您上次的访问时间是:"+lasttime);
                break;
            }
        }
        if (lasttime==null){
            out.print("您是第一次访问本网站");
        }
        Date date = new Date();
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        String strDate=simpleDateFormat.format(date);
        Cookie cookie=new Cookie("lastDate", URLEncoder.encode(strDate,"utf-8"));
        cookie.setMaxAge(60);
        resp.addCookie(cookie);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

Session

Session:服务器端的会话技术,它可以把同一用户与服务器多次请求响应的一些数据记录在服务器Session域中,时间该用户在本次会话中,可以随时获取Session域中的对象,满足多次请求响应之间进行数据传递和访问

  • Session与Cookie是紧密相关的,Session的使用需要用户浏览器支持Cookie,如果浏览器不支持Cookie,或者禁用了Cookie,那么将不能使用Session

在这里插入图片描述

可以说这个JSESSIONID它代表了一个服务器上的一次会话的唯一标识的ID,浏览器每次的请求头Cookie中一直保存这一个JSESSIONID,就可以维持这一次会话

Session使用的场景:

  • 保存用户登录后的一些信息、操作
  • 这些数据可以在让用户在不同的页面使用

获取Session对象:

  • public HttpSession getSession();
    
    • 调用此方法时,容器会先检查客户端先前送出的请求是否 有建立过HTTP会话: 如果没有:容器会新建一个会话,并赋予一个唯一的会话ID。 如果有:容器会根据客户请求中的会话ID找到相匹配的会话。
  • public HttpSession getSession(boolean flag) ;
    
    • 此方法的flag是用来指定是否有必要创建一个 会话,如果flag为false,那么如果是第一次建立会话,则返回null,不会自动创建一个新的会话

HttpSession的常用方法:

返回值方法名说明
booleanisNew()判断是否为新建的会话
longgetCreationTime()获取该Session创建时间(毫秒值)
StringgetId()获取会话的ID
longgetLastAccessedTime()获取上次访问此会话的时间
ServletContextgetServletContext()获取该会话所在的ServletContext对象
voidsetAttribute(String var1, Object var2)将指定键和值存放到会话中
ObjectgetAttribute(String var1)获取会话中的指定值,根据键
voidremoveAttribute(String var1)移除会话中的指定值,根据键
voidinvalidate()结束会话
voidsetMaxInactiveInterval(int var1)设置会话超时的时间
longgetMaxInactiveInterval()获取会话的超时时间

方法演示:

@WebServlet(urlPatterns = {"/session1"})
public class SessionDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        HttpSession session = req.getSession();
        PrintWriter out = resp.getWriter();
        if (session.isNew()){
            out.print("这是一个新的会话"+session.getId()+"<br>");
        }else {
            out.print("这是一个已存在的会话"+session.getId()+"<br>");
        }
        //设置会话的存活时间(一小时,默认应该为半小时)
        session.setMaxInactiveInterval(3600);
        SimpleDateFormat dateFormat = new SimpleDateFormat();

        out.print("会话的创建时间为:"+dateFormat.format(session.getCreationTime())+"<br>");
        out.print("会话的上次访问时间为:"+session.getLastAccessedTime()+"<br>");
        out.print("会话的最大存活时间为:"+session.getMaxInactiveInterval()+"<br>");
        //结束会话
//        session.invalidate();
    }
}

URL重写

上面讲到Cookie不安全的问题,如果用户浏览器禁用了Cookie,那么我们就无法实现会话技术,这时,我们就要采用另一种方式来保存我们会话的标识,维持我们的会话

使用URL重写:

将会话ID添加到URL结尾后面,这样服务器可以根据请求URL后面的会话ID来匹配和用户之间相应的会话。

HttpServletResponse接口中提供了两个用于完成URL重写的方法

  • String encodeURL(String url) 对超链接或form表单的action属性中设置的URL进行重写。
  • String encodeRedirectURL(String url) 对要传递给sendRedirect()方法的URL进行重写。
        //向会话域中添加数据
        session.setAttribute("key1","hahaha");
        String url = resp.encodeRedirectURL("session.jsp");
//        resp.sendRedirect(url);//重定向到jsp页面,因为是同一次会话,该页面也可以查看保存在session中的数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Session测试</title>
</head>
<body>
<%= session.getAttribute("key1").toString()%>
<a href="<%= response.encodeURL("index.jsp")%>">超链接也可以使用URL重写</a>
</body>
</html>

在这里插入图片描述

在这里插入图片描述

进行url重写后,在浏览器中设置禁用Cookie,此时在url后就可以看到重写后的url(不禁用的情况下可能看不到)

在这里插入图片描述

补充:
Session和Cookie之间的区别

CookieSession
客户端浏览器的会话技术服务器端的会话技术
将服务器传递的一些数据保存在浏览器上(Cookie)将同一用户和服务器的多次请求和响应产生的信息保存在Session(会话)域中
这些数据由浏览器来决定存不存储,不太安全(也可能被人为修改)保存在服务器中,相对安全一些(这里的安全是指会不会丢失)
存储的数据必须是小量文本信息存储的数据可以是任意数量大小、任意类型
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值