大数据正式18

大数据正式18

验证码校验

1. regist.jsp中提交的有验证码信息
2. RegistServlet中,验证用户提交的信息和验证码生成时的信息是否一致,并进行相应的处理
  • 验证流程
  • EasyMall代码改造

    • ValiImageServlet【把验证码的数据存储到session中】

      package com.easymall.ser;
      
      import java.awt.Color;
      import java.awt.Font;
      import java.awt.Graphics2D;
      import java.awt.image.BufferedImage;
      import java.io.IOException;
      import java.util.Random;
      
      import javax.imageio.ImageIO;
      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      
      @SuppressWarnings("serial")
      public class ValiImageServlet extends HttpServlet {
          // 背景参数
          private int base = 30;
          private int height = base;
          private int width = base * 4;
      
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                  throws ServletException, IOException {
              // 禁止浏览器缓存图片
              resp.setHeader("Cache-Control", "no-cache");
              resp.setHeader("Progma", "no-cache");
              resp.setDateHeader("Expires", 0);
              // 创建内存中的图片
              BufferedImage di = new BufferedImage(width, height,
                      BufferedImage.TYPE_INT_RGB);
              // 获取画布画背景
              Graphics2D g2 = (Graphics2D) di.getGraphics();
              // 填充矩形
              g2.setColor(Color.white);
              g2.fillRect(0, 0, width, height);
              // 绘制边框
              g2.setColor(Color.red);
              g2.drawRect(0, 0, width - 1, height - 1);
              // 写字并保存到session
              String valistr2 = "";
              g2.setFont(new Font("微软雅黑", Font.BOLD, 25));
              for (int i = 0; i < 4; i++) {
                  String s = Integer.toString(getRandom(0, 10));
                  valistr2 += s;
                  g2.setColor(new Color(getRandom(0, 255), getRandom(0, 255),
                          getRandom(0, 255)));
                  int temp = getRandom(-45, 45);
                  g2.rotate(temp / 180.0 * Math.PI, 10 + 30 * i, 20);
                  g2.drawString(s, 10 + 30 * i, 20);
                  g2.rotate(-temp / 180.0 * Math.PI, 10 + 30 * i, 20);
              }
              System.out.println("当前验证码:" + valistr2);
              req.getSession().setAttribute("valistr2", valistr2);
              // 画干扰线
              for (int i = 0; i < 3; i++) {
                  g2.setColor(new Color(getRandom(0, 255), getRandom(0, 255),
                          getRandom(0, 255)));
                  g2.drawLine(getRandom(0, width), getRandom(0, height),
                          getRandom(0, width), getRandom(0, height));
              }
              // 画干扰点
              for (int i = 0; i < 5; i++) {
                  g2.setColor(new Color(getRandom(0, 255), getRandom(0, 255),
                          getRandom(0, 255)));
                  g2.drawOval(getRandom(0, width), getRandom(0, height), 5, 5);
              }
              // 画出图片
              ImageIO.write(di, "JPG", resp.getOutputStream());
              // 关闭画布
              g2.dispose();
          }
      
          @Override
          protected void doPost(HttpServletRequest req, HttpServletResponse resp)
                  throws ServletException, IOException {
              this.doGet(req, resp);
          }
      
          // 获取随机数
          private int getRandom(int start, int end) {
              Random random = new Random();
              return start + random.nextInt(end - start);
          }
      
      }
      
    • RegistServlet【注册逻辑中添加两个验证码数据的校验过程】

      package com.easymall.ser;
      
      import java.io.IOException;
      import java.sql.Connection;
      import java.sql.PreparedStatement;
      import java.sql.ResultSet;
      
      import javax.servlet.ServletContext;
      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      
      import com.easymall.exception.MsgException;
      import com.easymall.utils.MySqlUtils;
      
      @SuppressWarnings("serial")
      public class RegisteSer extends HttpServlet {
          private Connection conn = null;
          private PreparedStatement stat = null;
          private ResultSet rs = null;
      
          public void doGet(HttpServletRequest request, HttpServletResponse response)
                  throws ServletException, IOException {
              // 全局变量
              try {
                  // 0.获取应用参数
                  ServletContext sc = this.getServletContext();
                  String encode = sc.getInitParameter("encode");
      
                  // 1.解决requestpost请求乱码 解决response输出数据乱码
                  request.setCharacterEncoding(encode);
                  response.setCharacterEncoding(encode);
                  response.setContentType("text/html;charset=" + encode);
      
                  // 2.获取请求参数
                  String username = request.getParameter("username");
                  String password = request.getParameter("password");
                  String password2 = request.getParameter("password2");
                  String nickname = request.getParameter("nickname");
                  String email = request.getParameter("email");
                  String valistr = request.getParameter("valistr");
      
                  // 验证码校验--获取请求参数的验证码,获取session中的验证码,对比并进行相应的操作
                  String valistr2 = (String) request.getSession().getAttribute(
                          "valistr2");
                  if (valistr == null || valistr2 == null
                          || !valistr.equals(valistr2)) {
                      request.setAttribute("msg", "验证码不正确!");
                      request.getRequestDispatcher(
                              request.getContextPath() + "/regist.jsp").forward(
                              request, response);
                      return;
                  }
                  // 3.检查数据有效性 如果有问题 向浏览器报错
                  if (username == null || "".equals(username)) {
                      throw new MsgException("用户名不能为空!");
                  }
      
                  if (password == null || "".equals(password)) {
                      throw new MsgException("密码不能为空!");
                  }
      
                  if (password2 == null || "".equals(password2)) {
                      throw new MsgException("确认密码不能为空!");
                  }
      
                  if (!password.equals(password2)) {
                      throw new MsgException("两次密码不一致!");
                  }
      
                  if (nickname == null || "".equals(nickname)) {
                      throw new MsgException("昵称不能为空!");
                  }
      
                  if (email == null || "".equals(email)) {
                      throw new MsgException("邮箱不能为空!");
                  }
      
                  if (!email.matches("^\\w+@\\w+(\\.\\w+)+$")) {
                      throw new MsgException("邮箱格式不正确!");
                  }
      
                  if (valistr == null || "".equals(valistr)) {
                      throw new MsgException("验证码不能为空!");
                  }
      
                  // 4.存入数据库
                  // 判断账号是否重复
                  conn = MySqlUtils.getConn();
                  stat = conn.prepareStatement("select * from user where username=?");
                  stat.setString(1, username);
                  rs = stat.executeQuery();
      
                  if (rs.next()) {// 账号重复
                      throw new MsgException("账号重复");
                  } else {// 账号不重复
                      stat = conn
                              .prepareStatement("insert into user values(?,?,?,?)");// 账号,密码,昵称,邮箱
                      stat.setString(1, username);
                      stat.setString(2, password);
                      stat.setString(3, nickname);
                      stat.setString(4, email);
                      stat.executeUpdate();
      
                  }
      
                  // 5.向浏览器报告成功 回到主页
                  response.getWriter().write("注册成功!正在前往主页------>>>");
                  response.setHeader("refresh", "1;url=" + request.getContextPath()
                          + "/index.jsp");
              } catch (MsgException e) {
                  String msg = e.getMessage();
                  response.getWriter().write(msg);
                  response.setHeader("refresh", "1;url=/regist.jsp");
              } catch (Exception e) {
                  e.printStackTrace();
                  throw new RuntimeException(e);
              } finally {
                  // 关闭数据库
                  MySqlUtils.close(conn, stat, rs);
              }
      
          }
      
          public void doPost(HttpServletRequest request, HttpServletResponse response)
                  throws ServletException, IOException {
              doGet(request, response);
          }
      
      }
      

数据回显

  • 原理:一次请求,一次响应的Request域对象没有被销毁,也没有被改变
  • 流程
    1. 浏览器注册请求【携带一些错误的注册信息存进req域】
    2. 服务器进行校验,发现错误,携带需要回显的数据回到注册界面
    3. 通过Request域获取需要回显的数据进行显示【此时还是属于注册的一次请求一次响应当中】
  • 流程图
  • 代码改造

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    
    
    
    欢迎注册EasyMall
    
    
    
    
    
    
        

    欢迎注册EasyMall

    用户名: ">
    密码:
    确认密码:
    昵称: ">
    邮箱: ">
    验证码: <%=request.getAttribute("msg") == null ? "" : request .getAttribute("msg")%>

session的工作原理

  • 重要的session的id号Jsessionid【cookie的键,值为浏览器访问的id值】
  • 服务器通过cookie来保存Jsessionid并作为响应头发送给浏览器存入,下次浏览器再次访问服务器数时,通过Jseeionid找服务器中对应的区域,如果找到则用里面的数据
  • 流程图

Cookie被禁用后--URL重写技术解决

  • 原理:将Jsessionid拼接在url后面
  • 如果禁用Cookie,浏览器就不再基于cookie来保存Jsessionid,在服务器中没有这个Jsessionid则找不到对应的Session
  • 解决这个问题,想办法携带Jsessionid来传给服务器---Url重写
    1. resp.encodeURL(String url)【普通的用这个】
    2. resp.RedirectUrl(String url)【重定向用这个】
  • 使用的优缺点
    • 缺点:所有的地址都要这个改变
    • 优点:即使浏览器禁用Cookie,用户也可以正常访问
  • 一般不进行url重写,因为这个错在用户禁用,可以警示用户,也可以引导用户打开浏览器的Cookie

Cookie和Session的区别

  Cookie Session
保存时间: 自行设置 默认30分钟
位置: 客户端保存数据 服务端保存数据
影响: 有可能随着用户的操作被删除 只要不刻意删除对应的数据,在存活期间可以可靠的访问
安全性: 不安全,可以翻看记录来获得相关的信息 安全,数据保存在服务器端
用途: 记住用户名 一次会话的信息:验证码

Cookie和Session的使用

  • 数据长时间保存:cookie
  • 安全性的选择:Session

继续JSP的学习

  • Jsp的指令
    • 格式:<%@ 指令名 若干属性 %>
    • 概述:不产生任何直接的输出,是用来控制jsp解析引擎,如何解析页面中的其他部分内容的
    • 指令
      1. page
        1. 功能:声明当前jsp的基本属性,指挥解析引擎如何翻译jsp页面中的其他部分内容
        2. 属性:
          1. extends:继承哪个类
          2. language:当前jsp使用的开发语言
          3. import:导包【自动导入的包:lang,javax.servlet.,javax.jsp.
          4. session:会话对象【禁止自动生成的sesion="false",默认为true】
          5. buffer
          6. autoFlush
          7. errorPage:错误页面
          8. isErrorPage:是否是错误页面【true/false】【会多一个Exception对象】
          9. contentTpye:
          10. pageEncoding:
          11. isELIgnored:是否支持EL表达式
      2. include
        1. 格式<%@ include file=""%>
        2. 功能:实现页面包含

          
              ...
                  
                      ...
                      ...
                                   
              ...
          
          
      3. taglib:引入标签库
    • 补充1:乱码
      1. jsp读取翻译的编码:pageEncoding="编码"【保存文件编码和页面编码一致】
      2. 翻译过来的servlet将数据通过Response发送给浏览器【response.setCharacterEncoding("utf-8")】【response.contentType("text/html;charset;utf-8")】这两个相当于:【contentType="text/html;charset=utf-8"】
      3. 上面的两个乱码可以合成一个:pageEncoding="编码"
        1. 文件保存编码
        2. jsp翻译编码
        3. 服务器发送编码
        4. 浏览器解析编码
    • 补充2:错误页面
      • errorPage属性可以配置错误页面,但是太麻烦了给所有的jsp页面
      • 可以在web.xml中配置全局的错误界面

        
            
            
        
        

        
            
            
        
        
      • 配置过全局的错误界面,也配置了具体的,执行具体的

jsp的九大隐式对象【内置的,隐藏的】

  • jsp直接创建的,可以直接拿来用的
    1. application(ServletContext当前web应用)
    2. config(当前Servlet的配置信息)
    3. out(response.getWriter)
    4. session(会话技术HttpSession)
    5. exception(Exception,如果将isError设置为true,则exception代表前一个错误页面的错误信息)
    6. page(代表Servlet)
    7. pageContext(代表当前页面)

      1. 代表当前jsp页面
      2. 作为入口参数获取其他八大隐式对象
      3. 是一个域对象【request,ServletContext,session,pageContext】
          1. 生命周期:访问jsp开始,访问完后销毁
          2. 作用范围:当前jsp页面
          3. 主要功能:
              1. 在当前jsp中共享数据
                  1. setAttribute(String,Objejct)
                  2. getAttribute(String)
                  3. removeAttribute(String)
              2. 作为入口对象操作四大作用域对象
                  1. setAttribute(String name,Objejct obj,int scope)
                  2. getAttribute(String,int scope)
                  3. removeAttribute(String,int scope)
                  4. 对应的域
                      1. PageContext.APPLICATION_SCOPE
                      2. PageContext.SESSION_SCOPE
                      3. PageContext.REQUEST_SCOPE
                      4. PageContext.PAGE_SCOPE
              3. findAttribute(String)
                  1. 寻找指定的对象
                  2. 搜寻的顺序【由小到大:pageContext、Request、session、application】
                  3. 找到返回,找不到返回null
              4. 转发pageContext.forward("路径");
              5. 包含pageContext.include("路径");
      
    8. request(请求)
    9. response(响应)
  • 记忆方法:【page,request,response,config,application,session,Exception,out,pageContext】
  • 对应所学:【Servlet,请求,响应,配置,web应用,会话,异常,输出,页面】

补充之jsp、Session、Cookie

你可能感兴趣的:(达内实训,大数据学习痕迹)