Servlet入门第四天——会话技术Cookie以及Session

文章目录

  • Servlet
    • 会话技术
      • Cookie
        • 通过Servlet设置Cookie
        • Cookie细节
        • Cookie的应用
      • Session
        • Session作为域对象
        • 生命周期和有效期
        • 利用Session 防止表单重复提交
        • 一次性校验码
      • session 和Cookie的区别

Servlet

通过这篇博客你将会学到如下知识:Servlet的会话技术,主要讲解了Cookie和Session如何使用以及他们之间的区别

会话技术

  • 用户开一个浏览器,访问一个网站,只要不关闭该浏览器,不管用户点击多少超链接,访问多少资源,直到用户关闭浏览器,整个过程称为一次会话

Cookie

  • 用户访问服务器的通行证
  • 流程:浏览器访问服务器,如果服务器需要记录该用户的状态,就使用response向浏览器发送一个Cookie,浏览器会把Cookie保存起来。当浏览器再次访问服务器时,浏览器会把请求的网址连同Cookie一同交给服务器
  • 识别返回用户包括三个步骤
    • 服务器脚本向浏览器发送一组Cookie。
    • 浏览器将这些信息存储在本地计算机上
    • 当下一次浏览器向Web服务器发送任何请求时,浏览器都会把这些Cookie信息发送到服务器,服务器将使用这些信息来识别用户。

通过Servlet设置Cookie

  • 创建一个Cookie对象
Cookie cookie = new Cookie("key","value");
  • 设置最大生存周期:以秒为单位
cookie.setMaxAge(60*60*24); 
  • 发送Cookie到Http响应头:
response.addCookie(cookie);

Cookie细节

  • 不可跨域名性
  • 有效期:通过MaxAge设置,默认值为-1
    • 正数:表示存活时间,存放在硬盘中,无论是关闭了浏览器还是电脑都有效
    • 负数:表示Cookie是临时性的,仅在本浏览器内有效,关闭就失效了,
    • 0:表示删除该Cookie
  • 修改和删除
    • 删除:通过MaxAge=0来控制
    • 修改:Cookie存储和Map差不多,只需要key不变,value进行改变就可以。
  • 域名:domain属性决定运行访问Cookie的域名
  • 路径:path属性
  • 安全属性:设置secure属性为true,浏览器只会在HTTPS和SSL等安全协议中传输该Cookie

Cookie的应用

  • 显示用户上次访问的时间:

    先检查所有的Cookie看是否有需要的,如果没有就是第一次登陆

            SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            response.setContentType("text/html;charset=UTF-8");
            PrintWriter printWriter=response.getWriter();
            //获取页面上所有的Cookie
            Cookie[] cookies=request.getCookies();
            //判断Cookie的值是否为空
            String cookieValue=null;
            for(int i=0;cookies!=null&&i<cookies.length;i++){
                //获取以time命名的Cookie,同时避免空指针异常
                if("time".equals(cookies[i].getName())){
                    printWriter.write("上次登录的时间是:");
                    cookieValue=cookies[i].getValue();
                    printWriter.write(cookieValue);
                    cookies[i].setValue(simpleDateFormat.format(new Date()));
                    response.addCookie(cookies[i]);
                    break;
                }
            }
            //如果Cookie为空代表第一次访问
            if(cookieValue==null){
                Cookie cookie=new Cookie("time",simpleDateFormat.format(new Date()));
                cookie.setMaxAge(20000);
                response.addCookie(cookie);
                printWriter.write("第一次访问!");
            }
    

    PS;容易出现一个问题

Servlet入门第四天——会话技术Cookie以及Session_第1张图片

由于Tomcat版本较高,所以在addCookie时是不能使用空格的 而在ASCII码中32对应的就是空格。只要把后台代码中的空格删掉就可以了。所以在时间那个,把空格换到就好

Session

  • 其是一章记录浏览器状态的机制,Cookie保存在浏览器中,Session保存在服务器中。用户使用浏览器访问服务器的时候,服务器把用户信息以某种形式记录在服务器中,这就是Session
    • Cookie是检查用户身上的通行证来确认用户的身份
    • Session是通过检查服务器上的客户明细表来确认用户身份
  • Session可以存储对象,而Cookie只能存储字符串
  • Session是依靠Cookie来识别不同的用户,但是要是禁用了Cookie要使用URL重写来解决

Session作为域对象

  • 其作为一种记录浏览器状态的机制,只要Session对象没有被销毁,Servlet之间就可以通过Session对象实现通讯。

    • 在第一个Servlet中设置Session的属性

      //获取Session对象
      HttpSession httpSession=request.getSession();
      //设置Session属性
      httpSession.setAttribute("name","看完记得点赞");
      
    • 在第二个Servlet中获取

      //获取Session
      HttpSession httpSession=request.getSession();
      String value=(String)httpSession.getAttribute("name");
      PrintWriter printWriter=response.getWriter();
      printWriter.write(value);
      
  • 一般来说,当我们要存进的是用户级别(只要浏览器不关闭,希望数据还存在就用Session来保存)的数据就用Session。

生命周期和有效期

  • Session在用户第一次访问服务器Servlet,jsp等动态资源就会被自动创建,Session保存在内存中

  • 如果访问HTML,IMAGE等静态资源Session不会被创建

  • Session生成后,只要用户继续访问,服务器就会更新Session的最后访问时间,无论是否对Session进行读写,服务器都会认为Session活跃了一次

  • Session有默认的超时时间30分钟,可以对其进行修改

    • 在tomcat/conf/web.xml中设置,对所有的WEB应用

      <session-config>          
      	<session-timeout>20session-timeout>       
      session-config>
      
    • 在单个web.xml中配置,对单个web有效,以这个问准

    • 通过setMaxInactiveInterval()方法设置(单位为秒)

      //设置Session最长超时时间为60秒,这里的单位是秒
      httpSession.setMaxInactiveInterval(60);
      System.out.println(httpSession.getMaxInactiveInterval());
      

    Session的有效期和Cookie的是不同的

    • session
      • 周期是指不活动时间,在时间内访问过会重新计时。
      • 重启了tomcat或者reload web应用,或者关机了,session也会失效
      • 通过invalidate()方法让session中的所有属性失效(常常用于安全退出)
      • 希望某个数据失效可以使用removeAttribute()
    • cookie生命周期按照累计的时间来计算的

利用Session 防止表单重复提交

  • 情况:

    • 在处理表单的Servlet中刷新
    • 后退在提交
    • 网络延迟,多次点击提交按键
  • 解决

    • 处理表单Servlet中刷新

    • 后退再提交

    • 网络延迟

      • 用JS来防止:用户第一次点击提交按钮后,就把数据提交到服务器,当用户再次点击时就不把数据提交给服务器

      • 监听用户提交事件

        <%@page contentType="text/html;charset=UTF-8"language="java"%>
        <html>
        <head>    
        	<title>表单提交</title> 
        	<script type="text/javascript">       
        		//定义一个全局标识量:是否已经提交过表单数据       
        		var isCommitted =false;
        		functiondoSubmit(){        
        			//false表示的是没有提交过,于是就可以让表单提交给Servlet        
        			if(isCommitted==false) {
                        isCommitted = true;           
        				return true;
        			}else{
                      	return false;            
                    }
                }
        	</script>
        </head>
        <body>
        <formaction="/ouzicheng/Servlet7" onsubmit="returndoSubmit()">
            用户名:<input type="text" name="username">  
        	<inputtype="submit"value="提交">
        </form>
        </body>
        </html>
        

一次性校验码

  • 防止暴力猜密码
  • 验证原理:生成验证码后,把验证码的数据存进Session域对象中,判断用户输入验证码是否和Session域对象的数据一致

实现:

  • 生成验证码图片:

    @WebServlet("/Demo")
    public class Demo extends HttpServlet {
        public Demo(){
            super();
        }
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
            //在内存中生成图片
            BufferedImage bufferedImage=new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
            //获取这张图片
            Graphics2D graphics2D=(Graphics2D) bufferedImage.getGraphics();
            //设置背景色为白色
            graphics2D.setColor(Color.white);
            graphics2D.fillRect(0,0,80,20);
            //设置图片的字体和颜色
            graphics2D.setFont(new Font(null,Font.BOLD,20));
            graphics2D.setColor(Color.BLUE);
            //生成随机数
            String randomNum=makeNum();
            //往这张图片上写数据
            graphics2D.drawString(randomNum,0,20);
            //将随机数存入Session
            request.getSession().setAttribute("randomNum",randomNum);
            //控制浏览器不缓存这张照片
            response.setHeader("Expires","-1");
            response.setHeader("Cache-Control","no-cache");
            response.setHeader("Pragma","no-cache");
            //通知浏览器以图片的方式打开
            response.setHeader("Content-type","image/jpeg");
            //把图片写给浏览器
            ImageIO.write(bufferedImage,"jpg",response.getOutputStream());
    
        }
        @Override
        protected void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
            doGet(request,response);
        }
        private String makeNum(){
            Random random=new Random();
            int num=random.nextInt(999999);
            //验证码的位数要六位,于是将随机数转化为字符串,并且添加不够的位数
            String randomNum=String.valueOf(num);
            //使用StringBuffer来拼接字符串
            StringBuffer stringBuffer=new StringBuffer();
            for(int i=0;i<6-randomNum.length();i++){
                stringBuffer.append("0");
            }
            return stringBuffer.append(randomNum).toString();
        }
    }
    
  • jsp显示页面

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>冢狐</title>
    </head>
    <body>
    <form action="Demo1" >
      用户名:<input type="text" name="username"><br>
      密码:<input type="password" name="password"><br>
      验证码:<input type="text" name="randomNum"><br>
      <img src="/web/Demo"><br><br>
      <input type="submit"value="提交">
    </form>
    </body>
    </html>
    
  • 验证Servlet

    @WebServlet("/Demo1")
    public class Demo1 extends HttpServlet {
        public Demo1(){
            super();
        }
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        }
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          String clint_randomNum = request.getParameter("randomNum");
          String session_randomNum = (String)request.getSession().getAttribute("randomNum");
          PrintWriter printWriter=response.getWriter();
          printWriter.write("输入的"+clint_randomNum);
          printWriter.write("存的"+session_randomNum);
        }
    }
    
    

session 和Cookie的区别

  • 存储方式上:
    • Cookie只能存储字符串,如果要存储非ASCII字符串还要对其编码。
    • Session可以存储任何类型的数据,可以把Session看成是一个容器
  • 隐私安全上
    • Cookie存储在浏览器中,对客户端是可见的。信息容易泄露出去。如果使用Cookie,最好将Cookie加密
    • Session存储在服务器上,对客户端是透明的。不存在敏感信息泄露问题。
  • 有效期上
    • Cookie保存在硬盘中,只需要设置maxAge属性为比较大的正整数,即使关闭浏览器,Cookie还是存在的
    • Session的保存在服务器中,设置maxInactiveInterval属性值来确定Session的有效期。并且Session依赖于名为JSESSIONID的Cookie,该Cookie默认的maxAge属性为-1。如果关闭了浏览器,该Session虽然没有从服务器中消亡,但也就失效了。
  • 对服务器的负担上
    • Session是保存在服务器的,每个用户都会产生一个Session,如果是并发访问的用户非常多,是不能使用Session的,Session会消耗大量的内存。
    • Cookie是保存在客户端的。不占用服务器的资源。像baidu、Sina这样的大型网站,一般都是使用Cookie来进行会话跟踪。
  • 从浏览器的支持上比较
    • 如果浏览器禁用了Cookie,那么Cookie是无用的了!
    • 如果浏览器禁用了Cookie,Session可以通过URL地址重写来进行会话跟踪。
  • 从跨域名上
    • Cookie可以设置domain属性来实现跨域名
    • Session只在当前的域名内有效,不可夸域名

你可能感兴趣的:(Servlet)