zoukankan      html  css  js  c++  java
  • 会话技术

    HTTP协议的特点:

    1. 应答式,必须先有请求才有响应.
    2. 明文传输.不安全.
    3. 无状态.服务器不会记录客户端的访问信息.

    Web技术基于第三点,也提出解决方案

    Cookie

    ​ 服务器在第一次客户端访问时,给客户端一个凭证,每次客户端访问时,将这个凭证带过来.这样服务器就可以识别.如果该凭证有效,则继续使用,否则服务器会给一个新的凭证.这个凭证由浏览器保存.保存在客户端.这时容易出现数据安全问题.由于这个信息存储在客户端上,更换浏览器就会丢失.更换了终端也会丢失.在实际开发中,Cookie的使用越来越少了.

    ​ Cookie可以用于:访问历史记录,购物车,记住密码。

    Cookie的使用

    cookie是服务器给客户端

    ​ 1.服务器创建Cookie

    ​ 2.在响应中,设置Cookie

    ​ 3.返回给客户端

    package com.sxt.controller;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class CookieServlet extends HttpServlet {
    	
    	private static final long serialVersionUID = -5312491120640167631L;
    
    	@Override
    	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		// 创建Cookie
    		Cookie cookie  = new Cookie("cookieName", "cookieValue");
    		// 设置cookie的存活时间    默认一次浏览器的退出,可以通过设置存活时间进行持久化  单位是 秒
    		cookie.setMaxAge(60*3);
    		// 获取cookie的存活时间
    		cookie.getMaxAge();
    		// 获取cookie的名称
    		cookie.getName();
    		// 获取cookie的值
    		cookie.getValue(); 
    		// 设置生效的资源路径  cookie默认是对当前整个项目有效
    		//cookie.setPath(uri);
    		// 设置只能HTTP协议进行读取.设置true 只能HTTP协议操作Cookie 客户端无法进行操作
    		//cookie.setHttpOnly(true);
    		// 设置cookie的访问域名
    		//cookie.setDomain(pattern);
    		Cookie cookie1  = new Cookie("cookieName1", "cookieValue1");
    		Cookie cookie2  = new Cookie("cookieName2", "cookieValue2");
    		Cookie cookie3  = new Cookie("cookieName3", "cookieValue3");
    		// 设置cookie
    		resp.addCookie(cookie);
    		resp.addCookie(cookie1);
    		resp.addCookie(cookie2);
    		resp.addCookie(cookie3);
    		req.getSession();
    	}
    }
    

    Cookie案例:记住密码

    package com.sxt.controller;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class LoginController extends HttpServlet {
    
    	private static final long serialVersionUID = 8806988355645425860L;
    
    	@Override
    	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		String userName = req.getParameter("userName");
    		String password = req.getParameter("password");
    		String rember = req.getParameter("rember");
    		// 记住密码
    		if("1".equals(rember)) {
    			Cookie userNameCookie = new Cookie("userName", userName);
    			userNameCookie.setMaxAge(60*60*24*3);
    			Cookie passwordCookie = new Cookie("password", password);
    			passwordCookie.setMaxAge(60*60*24*3);
    			resp.addCookie(userNameCookie);
    			resp.addCookie(passwordCookie);
    		}else {
    			// 不记住密码 删除Cookie
    			Cookie[] cookies = req.getCookies();
    			if(cookies != null) {
    				for (Cookie cookie : cookies) {
    					String name = cookie.getName();
    					if(name.equals("userName")) {
    						// Cookie 设置为0  删除Cookie
    						cookie.setMaxAge(0);
    						resp.addCookie(cookie);
    					}
    					if(name.equals("password")) {
    						cookie.setMaxAge(0);
    						resp.addCookie(cookie);
    					}
    				}
    			}
    		}
    	}
    
    }
    
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    
    <form action="login.do" >
    	<p>
    		用户名:<input type="text" name="userName" value="${cookie.userName.value}" />
    	</p>
    	<p>
    		密码:<input type="text" name="password" value="${cookie.password.value}" />
    	</p>
    	<p>
    		记住密码:<input type="checkbox" name="rember" value="1" />
    	</p>
    	<input type="submit" value="提交" />
    </form>
    
    </body>
    </html>
    

    Session:表示一次会话

    Session存储在服务器.Session存储任意数据.并且Session是依赖Cookie的.服务器会给浏览器一个Cookie信息,JSESSIONID是Session的ID,浏览器每次请求会将这个信息带到服务器,从而换取Session.

    Session和Coolie的关系

    ​ session的本质,是存储在服务器内存中的一个对象。根据Cookie中JSESSIONID的值查找。

    注意: 在JSP页面中,默认会创建Session。但是在Servlet中,需要手动的创建。

    ​ 根据不同的JSESSIONID,会从服务器获取不同的Session对象。所以,不同客户端其使用的Session是不一样的。若JSESSIONID不一样,那么其获取的Session也不一样。

    示例

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    	// req.getSession() : 获取与当前请求相关的session对象  若没有则创建一个
    	// 获取了一个session
    	HttpSession session = req.getSession();
    	session.setAttribute("keyName", "value");
    	/*
    	由于服务器获取session 是根据cookie中 JSESSIONID的值  获取。但是Cookie默认是存在客户端的内存中,一旦客户端关闭
    	Cookie 会消失。则找不到之前的SESSION了
    	创建一个Cookie  且这个Cookie设置生命周期,让客户端将这个Cookie进行持久化。然后将SESSION的ID值存在这个COOKIE中
    	关闭浏览器。再次打开浏览器  进行访问。此时会自动将COOKIE带给服务器。而COOKIE中有JESSIONID,若找到了。*/
    	System.out.println("session地址:"+session);
    	//获取SESSION的ID
    	String id = session.getId();
    	Cookie cookie = new Cookie("JSESSIONID",id);
    	cookie.setMaxAge(60*60);
    	resp.addCookie(cookie);
    	resp.getWriter().print("Hello ");
    }
    
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    	// req.getSession() : 获取与当前请求相关的session对象  若没有则创建一个
    	//获取了一个session
    	HttpSession session = req.getSession();
    	System.out.println(session.getAttribute("keyName").toString());
    	System.out.println("session地址:"+session);
    	resp.getWriter().print("Hello ");
    }
    

    Session的应用场景

    ​ 当前用户,即用户登录后将用户信息放入session中,然后以后取的时候,直接从session中取.

    ​ 验证码,将验证码放入session,用户输入的验证,与session验证码进行对比.一致,则通过.

    Session的局限性

    ​ 由于Session是存储在服务器内存中,若服务器是多个节点的,则session无法共享.session失效了.在生产场景中,若是多台服务器,一般使用中间件存储session.

    如何使用Session

    1. 创建Session

      req.getSession();		//若当前不存在session  则创建新的session  否则返回当前session
      req.getSession(true);	//若当前不存在session  则创建新的session  否则返回当前session
      req.getSession(false);	//若当前存在session 	  则返回当前session  否则返回null
      
    2. 设置session的有效期

      session.setMaxInactiveInterval(interval); //设置session的有效期(单位是秒),若不大于0 则表示永久有效
      
    3. 设置session失效

      invalidate();	// 不让任何对象绑定这个session. 则request 找不到这个session.
      
    4. session属性相关操作

      session.setAttribute(name, value) // 设置session中的属性值
      session.getAttribute(name)		//根据name 获取对应的属性值
      session.getAttributeNames()		//获取session 所有属性的name值
      session.removeAttribute(name)	//删除属性值
      

    Session的使用

    package com.sxt.controller;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    @WebServlet(urlPatterns = {"/session.do"})
    public class SessionServlet extends HttpServlet {
    	private static final long serialVersionUID = -5145647028038928413L;
    
    	@Override
    	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		// 获取Session 获取一个与当前request对象关联的session
    		HttpSession session = req.getSession();
    		// 设置属性值
    		//session.setAttribute(name, value);
    		//session.getAttribute(name);
    		//session.getAttributeNames();
    		//session.removeAttribute(name);
    		// 获取sessionID
    		System.out.println(session.getId());
    		// 设置session的存活时间,  0  或者 负数  表示永远有效   服务器默认session失效是  30分钟
    		//session.setMaxInactiveInterval(interval);
    	}
    
    }
    

    Session案例

    使用Session存储当前用户

    private void login(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    	String userName = req.getParameter("userName");
    	String password = req.getParameter("password");
    	User user = userService.login(userName, password);
    	if(user != null) {
    		//跳转到学生列表 : 跳转到学生列表 : 学生列表页面必须要有数据
    		//获取session
    		HttpSession session = req.getSession();
    		//将用户信息放入session
    		session.setAttribute("user", user);
    		resp.sendRedirect("student.do?service=list");
    	}else {
    		resp.sendRedirect("login.jsp");
    	}
    }
    
    <p>欢迎您:${user.realName}</p>
    

    Session验证码

    hutool工具类方案:

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    	// 生成验证码  200:宽度   100:高度  4:验证码字符数  10:干扰元素的个数
    	AbstractCaptcha circleCaptcha = CaptchaUtil.createCircleCaptcha(200, 100, 4, 10);
    	circleCaptcha = CaptchaUtil.createLineCaptcha(200, 100,4, 10);
    	// 验证码对象中验证码字符串
    	String code = circleCaptcha.getCode();
    	System.out.println(code);
    	// 获取缓存图片对象   
    	BufferedImage image = circleCaptcha.getImage();
    	// 将验证码图片进行输出
    	circleCaptcha.write(resp.getOutputStream());
    }
    

    自定义验证码:

    package com.sxt.controller;
    
    import java.awt.Color;
    import java.awt.Font;
    import java.awt.Graphics;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.util.Random;
    
    import javax.imageio.ImageIO;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * @ClassName: CheckCodeServlet2 
     * @Description: 绘制 验证码
     * @author: Mr.T
     * @date: 2019年11月2日 下午2:06:23
     */
    @WebServlet(urlPatterns = {"/checkCode2.do"})
    public class CheckCodeServlet2 extends HttpServlet {
    
    	private static final long serialVersionUID = -8930649588155434394L;
    	
    	private static final String[] str = {"1","2","3","4","5","6","7","8","9","A","B","C","D"};
    	
    	@Override
    	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		/**
    		 * 	1. 产生一个验证码字符串
    		 * 	2. 将验证码字符串 绘制到图片
    		 * 	3.将图片输出到页面
    		 */
    		String code = getCode(4);
    		BufferedImage image = getImage(200, 100, code);
    		ImageIO.write(image, "jpg", resp.getOutputStream());
    	}
    	
    	/**
    	 * @Title: getImage
    	 * @author: Mr.T   
    	 * @date: 2019年11月2日 下午2:15:20 
    	 * @Description: 产生验证码图片
    	 * @param w
    	 * @param h
    	 * @param code
    	 * @return
    	 * @return: BufferedImage
    	 */
    	private BufferedImage  getImage(int w,int h,String code) {
    		//创建图片 画布
    		BufferedImage image = new BufferedImage(w, h,BufferedImage.TYPE_INT_RGB);
    		//获取画布相关画笔
    		Graphics graphics = image.getGraphics();
    		//设置画笔的颜色
    		graphics.setColor(Color.WHITE);
    		//绘制矩形
    		graphics.fillRect(0, 0, 200, 100);
    	
    		//创建字体
    		Font font = new Font("微软雅黑", Font.BOLD, 50);
    		graphics.setFont(font);
    		for (int i = 0; i < code.length(); i++) {
    			//设置画笔颜色
    			graphics.setColor(getColor());
    			char c = code.charAt(i);
    			graphics.drawString(""+c,10+(i*50),70);
    		}
    		//绘制干扰线
    		for (int i = 0; i < 10; i++) {
    			graphics.setColor(getColor());
    			graphics.drawLine(getX1(w),getY(h), getX2(w),getY(h));
    		}
    		return image;
    	}
    	
    	/**
    	 * @Title: getCode
    	 * @author: Mr.T   
    	 * @date: 2019年11月2日 下午2:13:46 
    	 * @Description: 产生验证码
    	 * @param codeCount
    	 * @return
    	 * @return: String
    	 */
    	public String getCode(int codeCount) {
    		String code = "";
    		for (int i = 0; i < codeCount; i++) {
    			int index = new Random().nextInt(str.length);
    			code = code + str[index];
    		}
    		return code;
    	}
    
    	/**
    	 * @Title: getColor
    	 * @author: Mr.T   
    	 * @date: 2019年11月2日 下午2:28:33 
    	 * @Description: 获取颜色
    	 * @return
    	 * @return: Color
    	 */
    	public Color getColor() {
    		Random random = new Random();
    		int r = random.nextInt(255);
    		int g = random.nextInt(255);
    		int b = random.nextInt(255);
    		Color color = new Color(r, g, b);
    		return color;
    	}
    	/**
    	 * @Title: getX1
    	 * @author: Mr.T   
    	 * @date: 2019年11月2日 下午2:41:22 
    	 * @Description: 产生起点
    	 * @param w
    	 * @return
    	 * @return: int
    	 */
    	public int getX1(int  w) {
    		w = w/2;
    		Random random = new Random();
    		return random.nextInt(w);
    	}
    	/**
    	 * @Title: getX2
    	 * @author: Mr.T   
    	 * @date: 2019年11月2日 下午2:43:54 
    	 * @Description: 终点的X值
    	 * @param w
    	 * @return
    	 * @return: int
    	 */
    	public int getX2(int  w) {
    		w = w/2;
    		Random random = new Random();
    		return random.nextInt(w)+w;
    	}
    	
    	/**
    	 * @Title: getY
    	 * @author: Mr.T   
    	 * @date: 2019年11月2日 下午2:44:08 
    	 * @Description: 随机产生Y轴值
    	 * @param h
    	 * @return
    	 * @return: int
    	 */
    	public int getY(int  h) {
    		Random random = new Random();
    		return random.nextInt(h);
    	}
    
    	public static void main(String[] args) {
    		String code = new CheckCodeServlet2().getCode(4);
    		System.out.println(code);
    	}
    	
    }
    

    总结:

    WEB会话技术.

    ​ HTTP协议的无状态,不会记录客户端的请求信息状态.

    WEB技术两种解决方案:

    ​ 1.Cookie

    ​ 客户端请求时 ,返回Cookie给客户端,客户端每次请求将Cookie带过来.

    ​ 2.Session

    ​ 服务器将数据信息,存储在服务器(创建了一个Session对象),然后将这个Session对象的唯一标识(Session的ID),利用Cookie给客户端,客户端每次请求,会将这个唯一标识通过Cookie传给服务器.服务器通过唯一标识,找到对应Session.

    局限性:

    ​ 1.Cookie存在客户端的,若多终端时,Cookie没法共享。

    ​ 2.Session存在服务器,多服务器是多节点,Session也无法做到完全共享。

  • 相关阅读:
    SolarWinds Orion API 远程代码执行漏洞(CVE-2020-10148)
    Lanproxy 路径遍历漏洞 (CVE-2021-3019)
    公众号文章集合-2020整理回顾
    PHPMailer远程命令执行漏洞复现
    SaltStack Shell 注入 (CVE-2020-16846)漏洞
    (CVE-2020-7961)Liferay Portal RCE 反序列化命令执行漏洞
    (CVE-2020-17530)Struts2 S2-061 远程命令执行漏洞复现
    ora-01722 无效数字
    公开课平台推荐
    PL/SQL Developer如何导出数据成sql的insert语句
  • 原文地址:https://www.cnblogs.com/lyang-a/p/12562937.html
Copyright © 2011-2022 走看看