百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

Web时代-Session和Cookie session和cookie的运行原理

lipiwang 2024-11-05 11:55 22 浏览 0 评论

今天我们继续回顾以往的知识点,今天我们将重新的认识关于会话技术的知识。

浏览器开始访问网站到访问网站结束期间产生的多次请求响应组合在一起叫做一次会话,会议话的过程中会产生会话相关的数据,我们需要将这些数据保存起来。

Cookie

Cookie是客户端的技术,程序把每个用户的数据以cookie的形式写给用户的各自的浏览器,当用户使用浏览器再去访问服务器中的web资源时,这样,web资源处理的就是用户各自的数据了。
Cookie是基于set-Cookie响应头和Cookie请求头工作的,服务器可以发送set-Cookie请求头命令浏览器保存一个cookie信息,浏览器会在访问服务器时以Cookie请求头的方式带回之前保存的信息cookie在浏览器中的存放只允许存300个cookie,每个站点最多有20个cookie在浏览器的存放cookie是不安全的,很有很能被丢失;
删除cookie必须设置maxAge path 一致性才可以覆盖

cookie是客户端技术

  • 数据保存在客户端,这个信息可以保存很长时间
  • 数据随时有可能被清空,所以cookie保存的数据是不太靠谱的
  • 数据被保存在了客户端,随时有可能被人看走,如果将一些敏感信息比如用户名密码等信息存在cookie中,可能有安全问题
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.setContentType("text/html;charset=utf-8");
        //创建cookie数组
        Cookie[] cookies=request.getCookies();
        Cookie findC=null;
        if(cookies!=null){
        for(Cookie c :cookies){
            if("lasttime".equals(c.getName())){
                findC=c;
            }
        }
        }
        if(findC==null){
            response.getWriter().write("你是第一次访问这个网站");
        }else{
            //cookies是返回一个long行的值
            Long lastTime=Long.parseLong(findC.getValue());
            response.getWriter().write("你上次访问的时间是:"+new Date(lastTime).toLocaleString());
        }
        Date date=new Date();
        Cookie cookie=new Cookie("lasttime", date.getTime()+"");
        //设置cookies保存的最多时间
        //相当于response中添加了一个Set-cookie的响应头
        cookie.setMaxAge(36000);
        //设置整个web应用的cookie信息都可以带过去;
        cookie.setPath(request.getContextPath());
        response.addCookie(cookie);
    }

setMaxAge与getMaxAge方法

  • 一个Cookie如果没有设置过MaxAge则这个Cookie是一个会话级别的Cookie,这个Cookie信息发给浏览器后浏览器会将它保存在浏览器的内存中,这意味着只要浏览器已关闭随着浏览器内存的销毁Cookie信息也就消失了.
  • 一个Cookie也可以设置MaxAge,浏览器一旦发现收到的Cookie被设置了MaxAge,则会将这个Cookie信息以文件的形式保存在浏览器的临时文件夹中,保存到指定的时间到来为止.这样一来即使多次开关浏览器,由于这些浏览器都能在临时文件夹中看到cookie文件,所以在cookie失效之前cookie信息都存在.
  • 想要命令浏览器删除一个Cookie,发送一个同名同path的cookie,maxage设置为0,浏览器以名字+path识别cookie,发现同名同path,cookie覆盖后立即超时被删除,从而就删除了cookie.就是一个覆盖.

setPath与getPath方法

用来通知浏览器在访问服务器中的哪个路径及其子路径时带着当前cookie信息过来如果不明确设置,则默认的路径是发送Cookie的Servlet所在的路径.

setDomain与getDomain方法


用来通知浏览器在访问哪个域名的时候带着当前的cookie信息.但是要注意,现代的浏览器一旦发现cookie设置过domain信息则会拒绝接受这个Cookie.我们平常不要设置这个方法.

Cookie是不可跨域名的。域名www.google.com颁发的Cookie不会被提交到域名www.baidu.com去。这是由Cookie的隐私安全机制决定的。隐私安全机制能够禁止网站非法获取其他网站的Cookie。

正常情况下,同一个一级域名下的两个二级域名如www.baidu.com和www.images.baidu.com也不能交互使用Cookie,因为二者的域名并不严格相同。如果想所有www.baidu.com名下的二级域名都可以使用该Cookie,需要设置Cookie的domain参数

Cookie cookie = new Cookie("time","20080808"); // 新建Cookie
cookie.setDomain("www.baidu.com"); // 设置域名
cookie.setPath("/"); // 设置路径
cookie.setMaxAge(Integer.MAX_VALUE); // 设置有效期
response.addCookie(cookie);              
/**
* 显示之前看的书从cookie中获取信息
**/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.setContentType("text/html;charset=utf-8");
        //查询数据库中的书的展示:
        Map<String, Book> map=BookDao.getbooks();
        for (Map.Entry<String, Book>entry :map.entrySet()) {
            Book book =entry.getValue();
            response.getWriter().write("<a href='"+request.getContextPath()+"/BookInfoServlet?id="+book.getId()+"'>"+book.getName()+"</a><br>");
        }
        response.getWriter().write("<hr>");
        //2`显示之前看过的书
        Cookie[] cookies=request.getCookies();
        Cookie findC=null;
        if(cookies!=null){
            for(Cookie c :cookies){
                if("last".equals(c.getName())){
                    findC=c;
                }
            }
        }
        if(findC==null){
            response.getWriter().write("你未浏览过");
        }else{
            response.getWriter().write("你浏览过书有:"+"<br/>");
            //cookies是返回一个long行的值
            String[] ids=findC.getValue().split(",");
            for(String id :ids){
                Book book=BookDao.getbook(id);
                //response.getWriter().write(book.getName()+"<br/>");
            }
        }
    }



Session

由于HTTP协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户,这个机制就是Session.典型的场景比如购物车,当你点击下单按钮时,由于HTTP协议无状态,所以并不知道是哪个用户操作的,所以服务端要为特定的用户创建了特定的Session,用用于标识这个用户,并且跟踪用户,这样才知道购物车里面有几本书。这个Session是保存在服务端的,有一个唯一标识。

session是服务器端技术,数据保存在服务区端,相对来说比较稳定和安全,占用服务器内存,所以一般存活的时间不会太长,超过超时时间就会被销毁.我们要根据服务器的压力和session 的使用情况合理设置session的超时时间,既能保证session的存活时间够用,同时不用的session可以及时销毁减少对服务器内存的占用.

作用范围:

当前会话范围

生命周期:

当程序第一次调用到request.getSession()方法时说明客户端明确的需要用到session此时创建出对应客户端的Session对象.

当session超过30分钟(这个时间是可以在web.xml文件中进行修改的)没有人使用则认为session超时销毁这个session.

程序中明确的调用session.invalidate()方法可以立即杀死session.

当服务器被非正常关闭时,随着虚拟机的死亡而死亡.如果服务器是正常关闭,还未超时的session会被以文件的形式保存在服务器的work目录下,这个过程叫做session的钝化.下次再正常启动服务器时,钝化着的session会被恢复到内存中,这个过程叫做session的活化.

作用:在会话范围内共享数据

session时间的配置:在配置的时是以分钟为单位的;
在web.xml中用配置<session-config><session-timeout>30</></>

session 的原理:

request.getSession()方法会检查请求中有没有JSESSIONID 如果没有则检查请求的URL后有没有以参数的形式带着JSESSIONID过来,如果有则找到对应的Session, 服务器如果找不到则认为这个浏览器没有对应的Session,创建一个Session然后再在响应中添加JSESSIONID

cookie的值就是这个Session 的id

默认情况下,JSESSIONID 的path为当前web应用的名称,并且没有设置过MaxAge,是一个会话级别的cookie.

这意味着一旦关闭浏览器再新开浏览器时,由于JSESSIONID丢失,会找不到之前的Session我们可以手动的发送JSESSIONID cookie,名字和path设置的和自动发送时一样,但是设置一下MaxAge,使浏览器除了在内存中保存JSESSIONID信息以外还在临时文件夹中以文件的形式保存,这样即使重开浏览器仍然可以使用之前的session

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        String prod=request.getParameter("prod");
        prod=new String(prod.getBytes("iso8859-1"),"UTF-8");
        HttpSession session=request.getSession();
        Cookie jc=new Cookie("JSESSIONID", session.getId());
        jc.setPath(request.getContextPath());
        jc.setMaxAge(1800);
        response.addCookie(jc);
        session.setAttribute("prod", prod);
    }
/**
*
*登录后将用户信息存到session中
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        //1.获取用户名密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //2.查询数据库检查用户名密码
        if(UserDao.valiNamePsw(username, password)){
            //3.如果正确登录后重定向到主页
            request.getSession().setAttribute("user", username);
            response.sendRedirect(request.getContextPath()+"/loginout/index.jsp");
            return;
        }else{
            //4.如果错误提示
            response.getWriter().write("用户名密码不正确!");
        }   
    }
/**
* 退出时把session杀死
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        //1.杀死session
        //request.getsession();如果没有session会创建一个
    if(request.getSession(false)!=null 
       && request.getSession().getAttribute("user")!=null){
        request.getSession().invalidate();
    }
    //2.重定向到主页
    response.sendRedirect(request.getContextPath()+"/loginout/index.jsp");
}
/**
* 防止form表单重复提交
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        request.setCharacterEncoding("utf-8");
        try {
            Thread.sleep(4*1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        String username = request.getParameter("username");
        String valinum = request.getParameter("valinum");
        String valinum2 = (String) request.getSession().getAttribute("valinum");
        if(valinum2!=null && !"".equals(valinum2) && valinum.equals(valinum2)){
            request.getSession().removeAttribute("valinum");
            System.out.println("向数据库中注册一次:"+username);
        }else{
            response.getWriter().write("from web:不要重复提交!!");
        }   
}

URL重写:

如果浏览器禁用了Cookie,浏览器就没有办法JSESSIONID cookie,这样就用不了Session了.我们可以使用URL重写的机制,在所有的超链接后都以参数的形式拼接JSESSIONID信息,从而在点击超链接时可以使用URL参数的方式带回JSESSIONID,从而使用Session将URL进行重写拼接上JSESSIONID的过程就叫做URL重写

request.getSession() --在URL重写之前一定要先创建出Session,才有Session id,才能进行重写
response.encodeURL()--- 一般的地址都用这个方法重写
response.encodeRedirectURL() --- 如果地址是用来进行重定向的则使用这个方法

url重写的方法一旦发现浏览器带回了任意cookie信息,则认为客户端没有禁用cookie,就不会再进行重写操作

以上就是本文分享的内容,如果喜欢请点个再看。

相关推荐

软件测试|MySQL CROSS JOIN:交叉连接的详细解析

简介在MySQL数据库中,CROSSJOIN是一种用于生成两个或多个表的笛卡尔积的连接方法。CROSSJOIN不需要任何连接条件,它将左表的每一行与右表的每一行进行组合,从而生成一个包含所...

「MySQL笔记」left join-on-and 与 left join-on-where 的区别

1.摘要关于这两种写法的重要知识点摘要如下:left-join时,即使有相同的查询条件,二者的查询结果集也不同,原因是优先级导致的,on的优先级比where高on-and是进行韦恩运算连接...

MySQL中的JOIN——联合查询的基本语法

MySQL中的JOIN指令用来将两个或多个表中的数据进行联合查询,根据连接条件来匹配记录,从而得到需要的结果集。在MySQL中,常见的JOIN类型包括INNERJOIN、LEFTJOIN和RIGH...

MySQL 中的 CROSS JOIN:强大的连接工具

CROSSJOIN在MySQL里是一种挺特别的连接操作,它能弄出连接表的笛卡尔积。这就是说,要是表A有m行,表B有n行,那ACROSSJOINB的结果就会有m*n...

大厂必问:MySQL 三表 JOIN 操作的解析与性能优化,效率又如何?

大厂必问:MySQL三表JOIN操作的解析与性能优化策略,效率又如何?点击关注,开启技术之旅!大家好,这里是互联网技术学堂,无论你是一名程序员、设计师、还是对技术充满好奇心的普通人,都欢迎你加入...

面试题:MySQL 的 JOIN 查询优化(mysql查询优化方法)

MySQL的JOIN查询优化是提升数据库性能的关键环节。以下是综合多个技术文档的核心优化策略,按优先级和实现难度分类:一、索引优化:性能提升的基础为连接字段建立索引确保参与JOIN的列(通常...

Flink中处理维表关联技术实现路径

在Flink中处理维表关联大体氛围TableSQLLookupJoin和DataStream算子函数,主要技术实现路径:I.FlinkSQL/TableAPI中的Lookup...

深入剖析Zookeeper原理(一)整体设计

1.ZK集群架构设计与特性1.ZK集群架构设计:ZK主要分为三种角色:Leader(领导者):一个Zookeeper集群同一时间只会有一个实际工作的Leader,它会发起并维护与各Follwer及...

多种负载均衡算法及其Java代码实现

首先给大家介绍下什么是负载均衡负载均衡建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。负载均衡,英...

一分钟了解SpringCloud中的ribbon到底是什么,原理是啥?

1.概念ribbon是一款客户端负载均衡器,用于微服务之间的负载均衡。首先,什么是客户端负载均衡?如图,ribbon可以通过注册中心获取服务列表,然后自己执行自己的负载均衡策略来决定要访问哪个微服务,...

Step by Step之腾讯云短信-验证码实践

在商城小程序和前端上线用了一阵子之后,用户提出了体验提升的需求,如忘记密码、绑定用户、快捷注册等,作为业界最佳实践的短信验证码登录、重置密码和注册等功能开发也就提上日程了,本文就以重置密码为例,将验证...

10分钟入门响应式:Springboot整合kafka实现reactive

Springboot引入Reactor已经有一段时间了,笔者潜伏在各种技术群里暗中观察发现,好像scala圈子的同仁们,似乎对响应式更热衷一点。也许是因为他们对fp理解的更深吧,所以领悟起来障碍性更少...

使用java随机生成有个性的用户名,LOL地名+水浒传,合计2808个

*随机生成用户名*取水浒传108好汉名字*取LOL地名26个,组合而成*一共可以生成2808个不同特色的用户名如果你在上网的时候,用户名难取的话,这里有很多可选择的用户名,现提供100个...

深入理解Math.random()的概率分布特性

直接上源码/***Returnsa{@codedouble}valuewithapositivesign,*返回一个带符号的double类型的数字,说人话就是返回一个非负...

编程英文 - 创建/生成/构建 (create/generate/build)

在软件开发中,create、generate和build这三个词经常被用到,它们都与"创造"或"产生"某些东西有关,但在具体使用场景和含义上有所不同。基本含义creat...

取消回复欢迎 发表评论: