JavaWeb学习--cookie和session

目录

(一)Cookie概述

1.什么叫Cookie

2.Cookie规范

 3.Cookie的覆盖

4.cookie的最大存活时间 ​​​​​​(Cookie的生命) 

(二) Cookie的API

1.创建Cookie:new  构造方法

 2.保存到客户端浏览器上,通过响应对象addCookie()

3.在服务器端获取cookie内容 请求对象:Cookie[] getCookies()  

(三)案例:记住我功能的实现

1.实现思路

第一步: 在servlet中写逻辑代码,判断是否勾选“记住我”

第二步:在login.jsp 获取服务器传过来的cookie的值,设置到表单元素上

(四) HttpSession

 1.什么是HttpSesssion

2.获取HttpSession对象

3.HttpSession是域对象

 4.案例:在登录中引入验证码

第一步:在login.jsp页面显示验证码

第二步:定义函数,在jsp页面编写refreshCode()方法

第三步:修改LoginServlet类的代码,当验证码错误时,显示“验证码错误”,若验证码不成功,不验证用户名和密码是否正确


(一)Cookie概述

1.什么叫Cookie

       Cookie翻译成中文是小甜点,小饼干的意思。在HTTP中它表示服务器送给客户端浏览器的小甜点。其实Cookie就是一个键和一个值构成的,随着服务器端的响应发送给客户端浏览器。然后客户端浏览器会把Cookie保存起来,当下一次再访问服务器时把Cookie再发送给服务器。

       Cookie是由服务器创建,然后通过响应发送给客户端的一个键值对。客户端会保存Cookie,并会标注出Cookie的来源(哪个服务器的Cookie)。当客户端向服务器发出请求时会把所有这个服务器Cookie包含在请求中发送给服务器,这样服务器就可以识别客户端了!

总结:

cookie特征:

  1. 创建于服务器,保存于客户端
  2. 不同的浏览器之间不能共享,
  3. 不能跨浏览器
  4. Cookie的key,value都是String
  5. 在之后的请求中,cookie会以请求头的方式自动发送给服务器

请求头:

缺点:

  1. 不安全,在客户端浏览器的键值不加密
  2. key,value的数据类型有限,只能存string类型的数据

2.Cookie规范

  • Cookie大小上限为4KB;(不同的浏览器cookie的内存大小可能不同

  • 一个服务器最多在客户端浏览器上保存20个Cookie;

  • 一个浏览器最多保存300个Cookie;

注意:

      不同浏览器之间是不共享Cookie的。也就是说在你使用IE访问服务器时,服务器会把Cookie发给IE,然后由IE保存起来,当你在使用FireFox访问服务器时,不可能把IE保存的Cookie发送给服务器。  

 3.Cookie的覆盖

       如果服务器端发送重复的Cookie那么会覆盖原有的Cookie,例如客户端的第一个请求服务器端发送的Cookie是:Set-Cookie: a=A;第二请求服务器端发送的是:Set-Cookie: a=AA,那么客户端只留下一个Cookie,即:a=AA。

       如果cookie的name与path一样, 覆盖value, 如果没有设置path: 默认值, 创建Cookie的资源上级路径  

虽然name相同,但path不一样,所以没有覆盖

name相同,path相同,覆盖

cookie的path:

  • localhost:8090/bbb

访问的cookie: path为/下的cookie

  • localhost:8090/user/ccc

访问的cookie: path为/下的cookie和path为/user下的cookie

  • localhost:8090/a/b/c/d: 能访问的cookie: /c 下, /b 下 /a下 /下

path为/下的cookie,可以被所有的资源访问

某个url能访问的cookie: path为父辈级目录的Cookie,

调用setPath()给cookie设置path

 

4.cookie的最大存活时间 ​​​​​​(Cookie的生命) 

默认存活时间:会话级别,浏览器关闭,这个cookie就会被删除

调用setMaxAge(int 参数) 设置最大存活时间 单位: 秒

-1: 会话级别

>0: 存活多少秒, 时间一到,浏览器自动清除

0: 立即删除cookie

会话的概念:客户端打开浏览器,访问服务器表示会话的开始

  1. 只要浏览器不关闭, 这次会话一直存在, 这次会话内所有的请求, 共享同一个session域
  2. 当客户端关闭浏览器, 表示会话的结束
  3. 类似于生活中的通话

(二) Cookie的API

1.创建Cookie:new  构造方法

构造方法:

 2.保存到客户端浏览器上,通过响应对象addCookie()

//创建Cookie保存到客户端浏览器上
        Cookie cookie1 = new  Cookie("k1","v100");
        Cookie cookie2 = new  Cookie("k2","v200");

        //cookie的设置代码,一定在addCookie()之前
        //给cookie设置最大存活时间
        cookie1.setMaxAge(150);
        cookie2.setMaxAge(150);

        //保存到客户端
        resp.addCookie(cookie1);
        resp.addCookie(cookie2);

添加成功:

3.在服务器端获取cookie内容 请求对象:Cookie[] getCookies()  

@WebServlet("/bbb")
public class BServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //获取客户端浏览器传递Cookie
      //  System.out.println(req.getHeader("Cookie"));
        Cookie[] cookies = req.getCookies();
        //循环遍历
        for (Cookie cookie : cookies) {
            //获取Cookie的key, value
            String name = cookie.getName();
            if(name.equals("username") || name.equals("pwd")){
                String value = cookie.getValue();
                System.out.println("key:"+name+",value:"+value);
            }
        }
    }

(三)案例:记住我功能的实现

登录成功之后, 把用户名,密码保存起来, 保存方式?

(1)服务器? 客户端? 选择方案: 客户端

(2)如果保存在服务器, 存在哪

(3)如果保存在客户端, 存在哪    存在客户端浏览器

在客户端浏览器上有这三个地方可以存

那么我们应该选择哪一个来保存我们的数据呢?

       因为我们需要实现的是登录成功之后,把用户名、密码保存起来,所以这两个数据应该在服务器端的逻辑代码执行完毕之后传给客户端,所以是服务器传给客户端的数据。

      1.本地存储 localStorage, 会话存储 sessionStorage: 纯js技术, java没有

      2.Cookie:js操作, java也能操作 

      所以我们选择使用cookie来存储从服务器端传来的数据,也就是登录成功之后的用户名和密码。

1.实现思路

登录成功之后,并且用户勾选了“记住我”用户名,密码保存到cookie

第一步: 在servlet中写逻辑代码,判断是否勾选“记住我”

LoginServlet代码:

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.设置post请求编码, 响应编码
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");

        //进行验证码验证
        String verify=req.getParameter("verifycode");
        HttpSession session=req.getSession();
        String code=(String)session.getAttribute("CHECKCODE_SERVER");
        if (code.equals(verify)){
            //2.获取请求参数
            String username = req.getParameter("user");
            String password = req.getParameter("password");
            //3.调用业务层LoginService的登录方法
            LoginService loginService = new LoginServiceImpl();
            LoginInfo loginInfo = loginService.login(username, password);
            if(loginInfo != null){  //登陆成功
                String rem=req.getParameter("rem");
                if(Objects.nonNull(rem)){
                    //把用户名,密码保存到cookie
                    Cookie cookie1 = new Cookie("username", username);
                    Cookie cookie2=new Cookie("pwd",password);
                    //设置存活时间  7天
                    cookie1.setMaxAge(60*60*24*7);
                    cookie2.setMaxAge(60*60*24*7);
                    //设置path为/  项目下任何资源可以访问
                    cookie1.setPath("/");
                    cookie2.setPath("/");
                    //保存到客户端
                    resp.addCookie(cookie1);
                    resp.addCookie(cookie2);
                }
                session.setAttribute("login",loginInfo);
                resp.sendRedirect("/index.jsp");
            }else{   //登录失败
                //转发到登录页面
                //把错误信息保存到request域
                req.setAttribute("error", "用户名或密码错误");
                req.getRequestDispatcher("/login.jsp").forward(req, resp);
            }
        }else{
            req.setAttribute("error","验证码错误");
            req.getRequestDispatcher("/login.jsp").forward(req,resp);
        }

    }
}

记住我部分:

第二步:在login.jsp 获取服务器传过来的cookie的值,设置到表单元素上

login.jsp代码:

<body>
<%
    Cookie[] cookies=request.getCookies();
    String username="";
    String password="";
    if(cookies!=null && cookies.length > 0){
        for (Cookie cookie:cookies){
            if(cookie.getName().equals("username")){
                username=cookie.getValue();
            }
            if (cookie.getName().equals("pwd")){
                password=cookie.getValue();
            }
        }
    }
%>
<div class="container" style="width: 400px;">
    <h3 style="text-align: center;">管理员登录</h3>
    <form action="/login" method="post">
        <div class="form-group">
            <label for="user">用户名:</label>
            <input type="text" name="user" class="form-control" id="user" placeholder="请输入用户名" value="<%=username%>"/>
        </div>

        <div class="form-group">
            <label for="password">密码:</label>
            <input type="password" name="password" class="form-control" id="password" placeholder="请输入密码" value="<%=password%>"/>
        </div>

        <div class="form-inline">
            <label for="vcode">验证码:</label>
            <input type="text" name="verifycode" class="form-control" id="verifycode" placeholder="请输入验证码" style="width: 120px;"/>
            <a href="javascript:refreshCode()"><img src="vcode" title="看不清点击刷新" id="vcode"/></a>
        </div>
        <div class="form-inline">
            <input type="checkbox" name="rem" class="form-control" id="rem" value="rem" />
            <label for="rem">记住我</label>
        </div>
        <hr/>
        <div class="form-group" style="text-align: center;">
            <input class="btn btn btn-primary" type="submit" value="登录">
        </div>
    </form>
    <!-- 出错显示的信息框 -->
    <div class="alert alert-warning alert-dismissible" role="alert">
        <button type="button" class="close" data-dismiss="alert" >
            <span>&times;</span>
        </button>
        <strong>${error}</strong>
    </div>
</div>
</body>

实现:

(四) HttpSession

Cookie和HttpSession的区别:

Cookie:创建于服务器,保存于客户端

HttpSession:域对象,创建于服务器,保存于服务器,同一次会话有效

 1.什么是HttpSesssion

javax.servlet.http.HttpSession接口表示一个会话,我们可以把一个会话内需要共享的数据保存到HttpSession对象中!

每一个客户端都有自己的Session

 session作用: 域对象功能, 存,取数据

2.获取HttpSession对象

通过request对象的getSession()来获取

  • HttpSession request.getSesssion():如果当前会话已经有了session对象那么直接返回,如果当前会话还不存在会话,那么创建session并返回

  • HttpSession request.getSession(boolean):当参数为true时,与requeset.getSession()相同。如果参数为false,那么如果当前会话中存在session则返回,不存在返回null;

3.HttpSession是域对象

  • HttpServletRequest:一个请求创建一个request对象,所以在同一个请求中可以共享request,例如一个请求从AServlet转发到BServlet,那么AServlet和BServlet可以共享request域中的数据;

  • ServletContext:一个应用只创建一个ServletContext对象,所以在ServletContext中的数据可以在整个应用中共享,只要不启动服务器,那么ServletContext中的数据就可以共享;

  • HttpSession:一个会话创建一个HttpSession对象,同一会话中的多个请求中可以共享session中的数据;

下面是session的域方法:

  • void setAttribute(String name, Object value):用来存储一个对象,也可以称之为存储一个域属性,例如:session.setAttribute(“xxx”, “XXX”),在session中保存了一个域属性,域属性名称为xxx,域属性的值为XXX。请注意,如果多次调用该方法,并且使用相同的name,那么会覆盖上一次的值,这一特性与Map相同;

  • Object getAttribute(String name):用来获取session中的数据,当前在获取之前需要先去存储才行,例如:String value = (String) session.getAttribute(“xxx”);,获取名为xxx的域属性;

  • void removeAttribute(String name):用来移除HttpSession中的域属性,如果参数name指定的域属性不存在,那么本方法什么都不做;

  • Enumeration getAttributeNames():获取所有域属性的名称;

 4.案例:在登录中引入验证码

生成验证码Servlet:

在一个矩形框内生成随机字符

/**
 * 验证码
 */
@WebServlet("/checkCode")
public class CheckCodeServlet extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
		
		//服务器通知浏览器不要缓存
		response.setHeader("pragma","no-cache");
		response.setHeader("cache-control","no-cache");
		response.setHeader("expires","0");
		
		//在内存中创建一个长80,宽30的图片,默认黑色背景
		//参数一:长
		//参数二:宽
		//参数三:颜色
		int width = 80;
		int height = 30;
		BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
		
		//获取画笔
		Graphics g = image.getGraphics();
		//设置画笔颜色为灰色
		g.setColor(Color.GRAY);
		//填充图片
		g.fillRect(0,0, width,height);
		
		//产生4个随机验证码,12Ey
		String checkCode = getCheckCode();
		//将验证码放入HttpSession中
		request.getSession().setAttribute("CHECKCODE_SERVER",checkCode);
		
		//设置画笔颜色为黄色
		g.setColor(Color.YELLOW);
		//设置字体的小大
		g.setFont(new Font("黑体",Font.BOLD,24));
		//向图片上写入验证码
		g.drawString(checkCode,15,25);
		
		//将内存中的图片输出到浏览器
		//参数一:图片对象
		//参数二:图片的格式,如PNG,JPG,GIF
		//参数三:图片输出到哪里去
		ImageIO.write(image,"PNG",response.getOutputStream());
	}
	/**
	 * 产生4位随机字符串 
	 */
	private String getCheckCode() {
		String base = "0123456789ABCDEFGabcdefg";
		int size = base.length();
		Random r = new Random();
		StringBuffer sb = new StringBuffer();
		for(int i=1;i<=4;i++){
			//产生0到size-1的随机值
			int index = r.nextInt(size);
			//在base字符串中获取下标为index的字符
			char c = base.charAt(index);
			//将c放入到StringBuffer中去
			sb.append(c);
		}
		return sb.toString();
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.doGet(request,response);
	}
}

第一步:在login.jsp页面显示验证码

<div class="form-inline">
    <label for="vcode">验证码:</label>
    <input type="text" name="verifycode" class="form-control" id="verifycode" placeholder="请输入验证码" style="width: 120px;"/>
    <a href="javascript:refreshCode()"><img src="vcode" title="看不清点击刷新" id="vcode"/></a>
</div>

第二步:定义函数,在jsp页面编写refreshCode()方法

<script type="text/javascript">
        function refreshCode() {
            //每次点击时,重新生成验证码
            console.log("refreshCode....")
            //选择器 #id名
            //获取到img标签   浏览器缓存,url没有变化,使用上一次缓存的内容
            //加一个时间戳,每一次都不一样,浏览器发现参数不一样,以为是新请求,不使用上一次缓存
            $("#vcode").attr("src","/checkCode?time="+new Date().getTime())
        }
    </script>

第三步:修改LoginServlet类的代码,当验证码错误时,显示“验证码错误”,若验证码不成功,不验证用户名和密码是否正确

//进行验证码验证
        String verify=req.getParameter("verifycode");
        HttpSession session=req.getSession();
        String code=(String)session.getAttribute("CHECKCODE_SERVER");
        if (code.equals(verify)){
            //2.获取请求参数
            String username = req.getParameter("user");
            String password = req.getParameter("password");
            //3.调用业务层LoginService的登录方法
            LoginService loginService = new LoginServiceImpl();
            LoginInfo loginInfo = loginService.login(username, password);
            if(loginInfo != null){  //登陆成功
                String rem=req.getParameter("rem");
                if(Objects.nonNull(rem)){
                    //把用户名,密码保存到cookie
                    Cookie cookie1 = new Cookie("username", username);
                    Cookie cookie2=new Cookie("pwd",password);
                    //设置存活时间  7天
                    cookie1.setMaxAge(60*60*24*7);
                    cookie2.setMaxAge(60*60*24*7);
                    //设置path为/  项目下任何资源可以访问
                    cookie1.setPath("/");
                    cookie2.setPath("/");
                    //保存到客户端
                    resp.addCookie(cookie1);
                    resp.addCookie(cookie2);
                }
                session.setAttribute("login",loginInfo);
                resp.sendRedirect("/index.jsp");
            }else{   //登录失败
                //转发到登录页面
                //把错误信息保存到request域
                req.setAttribute("error", "用户名或密码错误");
                req.getRequestDispatcher("/login.jsp").forward(req, resp);
            }
        }else{
            req.setAttribute("error","验证码错误");
            req.getRequestDispatcher("/login.jsp").forward(req,resp);
        }

结果:

登录成功

验证码错误

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/930715.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

策略模式实战 - 猜拳游戏

**可以整体的替换一套算法&#xff0c;这就是策略模式。**这样对于同一个问题&#xff0c;可以有多种解决方案——算法实现的时候&#xff0c;可以通过策略模式来非常方便的进行算法的整体替换&#xff0c;而各种算法是独立封装好的&#xff0c;不用修改其内部逻辑。 具体的实…

Transformer简述和实现

Transformer 1、概述 (一)、诞生 自从2017年此文《Attention is All You Need》提出来Transformer后&#xff0c;便开启了大规模预训练的新时代&#xff0c;也在历史的长河中一举催生出了GPT、BERT这样的里程碑模型。 (二)、优势 相比之前占领市场的LSTM和GRU模型&#xf…

Astro 5.0 发布

Astro 5.0 发布&#xff01; 使用 Astro Content Layer 可以从任何来源加载内容&#xff0c;并使用 Server Islands 将缓存的静态内容与动态个性化内容结合起来。 什么是 Astro Astro 是用于构建内容驱动网站&#xff08;包括博客、营销和电子商务&#xff09;的 Web 框架。…

数据结构与算法-03链表-04

链表与递归 在链表操作中移除、反转经常会用到递归实现。通过力扣案例理解链表常规操作中的递归实现。 移除数据 删除链表的节点 问题 LCR 136. 删除链表的节点 - 力扣&#xff08;LeetCode&#xff09; 问题描述 给定单向链表的头指针和一个要删除的节点的值&#xff0c;定…

Let up bring up a linux.part2 [十一]

之前的篇幅中我们已经将 Linux 内核 bringup 起来了&#xff0c;不知道大家有没有去尝试将根文件系统运行起来&#xff0c;今天我就带领大家完成这个事情&#xff0c;可以跟着下面的步骤一步步来完成&#xff1a; 在这里我们使用 busybox 构建 rootfs&#xff1a; 下载 busyb…

WEB开发: Node.js路由之由浅入深(一) - 全栈工程师入门

作为一个使用Node.js多年的开发者&#xff0c;我已经习惯于用Node.js写一些web应用来为工作服务&#xff0c;因为实现快速、部署简单、自定义强。今天我们一起来学习一个全栈工程师必备技能&#xff1a;web路由。&#xff08;观看此文的前提是默认你已经装好nonde.js了&#xf…

新书速览|循序渐进Node.js企业级开发实践

《循序渐进Node.js企业级开发实践》 1 本书内容 《循序渐进Node.js企业级开发实践》结合作者多年一线开发实践&#xff0c;系统地介绍了Node.js技术栈及其在企业级开发中的应用。全书共分5部分&#xff0c;第1部分基础知识&#xff08;第1&#xff5e;3章&#xff09;&#xf…

二代证信息读写器安卓身份证手持终端pda

HT530是一款可满足不同应用需求的多功能身份证核验手持机。Android 10操作系统&#xff0c;搭载高性能8核心2.0G主频处理器&#xff0c;5.5寸高清大屏&#xff0c;1300万摄像头&#xff1b;内存2G16G,4G64G可选。条码扫描&#xff08;扫描头可选&#xff09;、可离线采集、读取…

Redis的高可用之哨兵模式

Redis哨兵主要是解决Redis主从同步时主数据库宕机问题,使其能够自动进行故障恢复&#xff0c;提高Redis系统的高可用性。 1. 哨兵的作用&#xff1a; 监控&#xff1a;哨兵通过心跳机制监控主库和从库的存活性。 选主&#xff1a;当主库宕机时&#xff0c;哨兵会选举出一个领…

2024最新版python+pycharm安装与配置(mac和window都有讲)

PS&#xff1a;这篇是对于初学者的pythonpycharm配置教程 &#xff0c;配置完成后可以直接看我的python学习笔记来进行python全套学习目前正在持续更新。 目录 python以及pycharm的安装配置一、下载安装Python1、python环境检查2、系统环境检查3、python下载4、开始安装5、检查…

【css】基础(二)

本专栏内容为&#xff1a;前端专栏 记录学习前端&#xff0c;分为若干个子专栏&#xff0c;html js css vue等 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;css专栏 &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&#x1f69a; &a…

OceanBase 的探索与实践

作者&#xff1a;来自 vivo 互联网数据库团队- Xu Shaohui 本文总结了目前我们遇到的痛点问题并通过 OceanBase 的技术方案解决了这些痛点问题&#xff0c;完整的描述了 OceanBase 的实施落地&#xff0c;通过迁移到 OceanBase 实践案例中遇到的问题与解决方案让大家能更好的了…

【开源免费】基于Vue和SpringBoot的服装生产管理系统(附论文)

博主说明&#xff1a;本文项目编号 T 066 &#xff0c;文末自助获取源码 \color{red}{T066&#xff0c;文末自助获取源码} T066&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析…

租赁小程序的优势与应用场景解析

内容概要 租赁小程序&#xff0c;听起来是不是很酷&#xff1f;其实&#xff0c;它就是一个让你可以方便地租借各种高成本但用得不频繁的商品的平台。想象一下&#xff0c;当你需要租一件派对用的华丽小礼服&#xff0c;或是想体验一下超酷的运动器材&#xff0c;租赁小程序就…

MySQL 权限管理分配详解

MySQL 权限管理分配详解 MySQL权限系统的工作原理权限表的存取用户通过权限认证、进行权限分配的流程账号管理我们常用的授权all privileges到底有哪些权限呢&#xff1f;以及带来的安全隐患有哪些&#xff1f;创建账户的时候最好分配指定的权限&#xff0c;这样子安全也高管理…

使用C#开发VTK笔记(一)-VTK开发环境搭建

一.使用C#开发VTK的背景 因为C#开发的友好性,一直都比较习惯于从C#开发程序。而长期以来,都希望有一个稳定可靠的三位工程数模的开发演示平台,经过多次对比之后,感觉VTK和OpenCasCade这两个开源项目是比较好的,但它们都是用C++编写的,我用C#形式开发,只能找到发布的C#组…

React 组件中 State 的定义、使用及正确更新方式

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;React篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来React篇专栏内容React 组件中 State 的定义、使用及正确更新方式 前言 在 React 应用开发中&#xff0c;state …

长沙市的科技查新机构有哪些

中南大学图书馆科技查新站&#xff1a; 中南大学图书馆科技查新站成立于2003年12月&#xff0c;中南大学图书馆科技查新站作为教育部首批批准的科技查新工作站之一&#xff0c;具备了在全国范围内开展科技查新工作的专业资质。 长沙理工大学科技查新工作站&#xff1a; 长沙理…

数组 - 八皇后 - 困难

************* C topic: 面试题 08.12. 八皇后 - 力扣&#xff08;LeetCode&#xff09; ************* Good morning, gays, Fridary angin and try the hard to celebrate. Inspect the topic: This topic I can understand it in a second. And I do rethink a movie, …