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 {@Overrideprotected 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, valueString 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 {@Overrideprotected 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)){//把用户名,密码保存到cookieCookie 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个随机验证码,12EyString 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)){//把用户名,密码保存到cookieCookie 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);}

结果:

登录成功

验证码错误

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL Binlog 日志监听与 Spring 集成实战

MySQL Binlog 日志监听与 Spring 集成实战 binlog的三种模式 MySQL 的二进制日志&#xff08;binlog&#xff09;有三种常见的格式&#xff1a;Statement 模式、Row 模式和Mixed 模式。每种模式的设计目标不同&#xff0c;适用于不同的场景&#xff0c;以下是它们的详细对比和…

Android上运行OpenCV(Android Studio)

用Android Studio的话&#xff0c;整体来说没什么难的&#xff0c;照着教程来做就好了。 【OpenCV】OpenCV库的安装 - Android与OpenCV系列教程_哔哩哔哩_bilibili 主要就是导入module&#xff0c;然后加入依赖。代码只有几行。 if(OpenCVLoader.initLocal()){Toast.makeText(…

VLDB 2024 | 时间序列(Time Series)论文总结

VLDB 2024于2024年8月26号-8月30号在中国广州举行。 本文总结了VLDB 2024有关时间序列&#xff08;time series data&#xff09;的相关论文&#xff0c;主要包含如有疏漏&#xff0c;欢迎大家补充。 时间序列Topic&#xff1a;预测&#xff0c;分类&#xff0c;异常检测&…

TongWeb7-东方通快速使用手册

TongWeb7-东方通 快速使用手册 文章目录 第1章 TongWeb7 产品介绍 1.1 概述1.2 规范支持 第2章 TongWeb7 安装 2.1 TongWeb7 安装要求 2.1.1 TongWeb7 支持的操作系统2.1.2 系统要求2.1.3 其他 2.2 安装TongWeb72.3TongWeb7 目录结构说明2.4 TongWeb7 的启动和停止 第3章 应用…

xtu oj 1618 素数个数

文章目录 前言代码思路 前言 有点儿难&#xff0c;至少对我来说。去年考试我没写出来。 代码 #include<stdio.h> #include<stdbool.h> #include<stdlib.h>//加 math 那个头文件好像要加这个头文件&#xff0c;我之前编译错误过&#xff0c;血泪教训 #incl…

非文件形式的内存动态函数库调用接口

使用memfd的系统调用接口将动态库加载到proc虚拟文件系统&#xff0c;提供的fd为进程持有的句柄&#xff0c;通过dlopen的path指向此句柄&#xff0c;即可实现非文件系统加载动态链接库。 文章目录 一、memfd_create二、dl_open三、示例参考 一、memfd_create 接口名称int mem…

ElfBoard开源项目|基于百度智能云平台的车牌识别项目

本项目基于百度智能云平台&#xff0c;旨在利用其强大的OCR服务实现车牌号码的自动识别。选择百度智能云的原因是其高效的API接口和稳定的服务质量&#xff0c;能够帮助开发者快速实现车牌识别应用。 本项目使用摄像头捕捉图像后&#xff0c;通过集成百度OCR服务的API&#xf…

【51单片机】程序实验1112.外部中断-定时器中断

主要参考学习资料&#xff1a;B站【普中官方】51单片机手把手教学视频 前置知识&#xff1a;C语言 单片机套装&#xff1a;普中STC51单片机开发板A4标准版套餐7 码字不易&#xff0c;求点赞收藏加关注(•ω•̥) 有问题欢迎评论区讨论~ 目录 程序实验11&12.外部中断-定时器…

Linux基础(2)完结

声明 学习视频来自 B 站up主泷羽sec&#xff0c;如有涉及侵权马上删除文章。 在学习的过程中记笔记&#xff0c;分享笔记方便各位师傅学习&#xff0c;以下内容只涉及学习内容&#xff0c;任何其他违法行为与本人及泷羽sec无关&#xff0c;请务必遵守法律法规&#xff0c;切莫逾…

【重生之我在B站学MySQL】

MySQL笔记 文章目录 MySQL的三层结构SQL语句分类sql语句数据库操作创建数据库查看、删除数据库 表操作创建表mysql常用数据类型(列类型)查询表、插入值创建表练习创建一个员工表emp 修改表mysql约束primary key(主键)not null(非空)unique(唯一)foreign key(外键)check自增长 索…

springSecurity自定义登陆接口和JWT认证过滤器

下面我会根据该流程图去自定义接口&#xff1a; 我们需要做的任务有&#xff1a; 登陆&#xff1a;1、通过ProviderManager的方法进行认证&#xff0c;生成jwt&#xff1b;2、把用户信息存入redis&#xff1b;3、自定义UserDetailsService实现到数据库查询数据的方法。 校验&a…

【adb】iqoo系统精简垃圾内置应用

免责声明 这个得谨慎点&#xff0c;虽然我验证过两部手机和不同版本的系统&#xff0c;但是总会有特殊的存在、 本教程来自于互联网搜集整理&#xff0c; 按照本教程造成的用户设备硬件或数据损失&#xff0c;本人概不承担任何责任&#xff0c;如您不同意此协议&#xff0c;请不…

计算机视觉:学习指南

一、引言 计算机视觉作为人工智能领域的一个重要分支&#xff0c;致力于让计算机理解和解释视觉信息&#xff0c;近年来取得了令人瞩目的进展&#xff0c;广泛应用于安防监控、自动驾驶、图像编辑、医学影像分析等众多领域。从入门到精通计算机视觉需要系统地学习一系列知识和…

汽车升级到底应不应该设置“可取消“功能

最近&#xff0c;汽车OTA&#xff08;Over-the-Air&#xff09;升级频频成为车主讨论的热点。有些车主反映&#xff0c;一些升级增加了实用功能&#xff0c;而另一些却让体验变得复杂甚至带来不便。于是&#xff0c;大家不禁发问&#xff1a;汽车升级功能究竟应不应该允许“可取…

三菱FX3uPLC输入接线注意事项

FX3u微型控制器(DC输入型)的输入根据外部接线&#xff0c;漏型输入和源型输入都可使用。 但是,一定要连接S/S端子的接线。 详细事宜请参考“FX3U系列微型控制器硬件说明手册 AC电源型的输入接线事例(FX3U-囗MR/UA1除外) DC电源型的输入接线事例 *请不要与(0V)、(24V)端子接线…

一文说清flink从编码到部署上线

引言&#xff1a;目前flink的文章比较多&#xff0c;但一般都关注某一特定方面&#xff0c;很少有一个文章&#xff0c;从一个简单的例子入手&#xff0c;说清楚从编码、构建、部署全流程是怎么样的。所以编写本文&#xff0c;自己做个记录备查同时跟大家分享一下。本文以简单的…

过滤器Filter,ajax异步请求,服务器响应的数据类型,json

1.过滤器Filter 按照过滤规则筛选出想要的资源 很多地方都需要判断是否登录&#xff0c;对每个资源进行判断&#xff0c;非常麻烦&#xff0c;可以使用过滤器在访问这些资源前进行判断。 案例&#xff1a; package com.ghx.filter;import javax.servlet.*; import javax.ser…

【网络协议栈】TCP/IP协议栈中重要协议和技术(DNS、ICMP、NAT、代理服务器、以及内网穿透)

每日激励&#xff1a;“请给自己一个鼓励说&#xff1a;Jack我很棒&#xff01;—Jack” 绪论​&#xff1a; 本章是TCP/IP网络协议层的完结篇&#xff0c;本章将主要去补充一些重要的协议和了解一些网络中常见的名词&#xff0c;具体如&#xff1a;DNS、ICMP、NAT、代理服务器…

服务器数据恢复—LINUX下各文件系统删除/格式化的数据恢复可行性分析

Linux操作系统是世界上流行的操作系统之一&#xff0c;被广泛用于服务器、个人电脑、移动设备和嵌入式系统。Linux系统下数据被误删除或者误格式化的问题非常普遍。下面北亚企安数据恢复工程师简单聊一下基于linux的文件系统&#xff08;EXT2/EXT3/EXT4/Reiserfs/Xfs&#xff0…

因果推荐CIKM24 | 通过偏好感知因果干预和反事实数据增强来提升序列推荐

论文来源&#xff1a;CIKM 24 论文链接&#xff1a;PACIFIC: Enhancing Sequential Recommendation via Preference-aware Causal Intervention and Counterfactual Data Augmentation | Proceedings of the 33rd ACM International Conference on Information and Knowledge …