会话技术Session

Session技术详解,包括如何获取和存取数据,生命周期,持久化,验证码校验及防止表单重复提交的策略。服务器端生成的JsessionId通过Cookie发送给客户端,在会话期间保持数据。Session默认30分钟后失效,可以通过invalidate()方法手动销毁。防止表单重复提交,服务器端通过生成唯一的Token保存在Session中,并在验证请求时检查Token的一致性。
摘要由CSDN通过智能技术生成

Session技术

Session 将数据存放在服务器端 , 获得session对象的同时 ,会为每一个客户端创建一块存放客户数据的区域,同时也会相应给客户端一个JsssionId的标识(Cookie ),当客户端在本次会话中再次访问时 ,都会携带 JsssionId 找到对应的session数据区域。 session是基于Cookie实现 。响应给客户端的Jsessionid不用自己管理 (自动完成)

Session

一:获取Session对象

	HttpSession session = request.getSession();		

获得session 服务器自动设置表示当前session唯一标识的jsessoinid (通过Cookie)发送给客户端

二: 存取数据 Session是一个域对象

	Session.setAttribute(String name,Object  o)
	Session.getAttribute(String name)
	Session.removeAttribute(String name)

三:Seesion 的生命周期

  • 创建:第一次获得session的时候 req.getSession()(jsp 页面 翻译成Servlet里面 也有获得session的方法 )

  • 销毁:1. 服务器关闭时 (客户端 丢失sessionid) 2.Session过期 /失效 (默认30分钟) 默认30可以改变,时间的起点是最后一次发送当前站点请求资源的时候,

     <!-- session 的过期时间  单位分钟 -->
     <session-config>
     	<session-timeout>1</session-timeout>
     </session-config>
    
  • 手动销毁:session.invalidate();

session作用范围: 默认在一次会话中 ,(一次会话中包含了多次请求和响应)

四:Session的持久化

JsessionId 保存Cookie中并设置过期时间

	//session持久化
	Cookie cookie = new Cookie("JSSIONID", session.getId());
	//设置过期时间
	cookie.setMaxAge(60 * 60);
	cookie.setPath("/web_session/getSessionlongtime");
	response.addCookie(cookie);
	response.sendRedirect("/web_session/welcome.jsp");

五:验证码的校验

1.首先生成一个验证码

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//获得word.txt的路径,在WEB-INF/word.txt中自己写验证码
String realPath = getServletContext().getRealPath("WEB-INF/word.txt");
//创建一个集合
List arrayList = new ArrayList();
//使用字符缓冲流,readLine()读一行的方法
BufferedReader bufferedReader = new BufferedReader(new FileReader(realPath));
String readLine = bufferedReader.readLine();
while (readLine != null) {
	arrayList.add(readLine);
	readLine = bufferedReader.readLine();
}

// 画一个验证码 随机验证码
int height = 30;
int width = 110;

// 内存中 画一个图片
BufferedImage bufferedImage = new BufferedImage(width, height,
		BufferedImage.TYPE_INT_RGB);

// 画笔
Graphics graphics = bufferedImage.getGraphics();

// 给图片添加背景颜色
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, width, height);
// 边框
graphics.setColor(Color.BLUE);
graphics.drawRect(0, 0, width - 2, height - 2);
// 写入验证码
// 设置字体
graphics.setFont(new Font("楷体", Font.BOLD, 20));
Random random = new Random();

Graphics2D graphics2D = (Graphics2D) graphics;
//从arrayList集合中随机取出一行数据
String mess = (String) arrayList.get(random.nextInt(arrayList.size()));

graphics2D.setColor(new Color(random.nextInt(255), random.nextInt(255),
		random.nextInt(255)));

// 弧度
int jiaodu = random.nextInt(15) - 7;

double theta = jiaodu * Math.PI / 180;

graphics2D.rotate(theta, (width / 6), 20);

graphics2D.drawString(mess, (width / 7), 22);

graphics2D.rotate(-theta, (width / 6), 20);

// 画干扰线
for (int i = 0; i < 5; i++) {
	graphics2D.setColor(new Color(random.nextInt(255), random
			.nextInt(255), random.nextInt(255)));
	graphics2D.drawLine(random.nextInt(width), random.nextInt(height),
			random.nextInt(width), random.nextInt(height));
	graphics2D.drawOval(random.nextInt(width), random.nextInt(height),
			2, 3);

}

// 给客户端响应图片
ImageIO.write(bufferedImage, "jpg", response.getOutputStream());

}
2.jsp页面访问

<%@ page language="java" contentType="text/html; charset=utf-8"
	pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
<script type="text/javascript">
	function code(jpg) {
		jpg.src = "/web06_session/responseCode?zz=" + new Date().getTime();
	}
</script>

</head>
<body>
	<form action="/web06_session/resposeCodeCheck" method="post">
		用户名<input type="text" name="username" /><br /> 密 &nbsp;&nbsp;码<input
			type="password" name="password" /><br /> 验证码 <input
			name="checkcode" /><img onclick="code(this)"
			src="/web06_session/responseCode" /> <input type="submit" />
	</form>
	<%
		if (request.getAttribute("error") != null) {
	%>
	<%=request.getAttribute("error")%>
	<%
		}
	%>
</body>
</html>

3.验证码验证

protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
	HttpSession session = request.getSession();
	// 获得前端的验证码
	request.setCharacterEncoding("utf-8");
	String checkcode = request.getParameter("checkcode");
	System.out.println(checkcode);
	
	if (session.getAttribute("checkcode") != null) {

		// 获得后台生成的
		String checkcodesession = (String) session.getAttribute("checkcode");

		// 比较验证码
		if (!checkcode.equals(checkcodesession)) {
			request.setAttribute("error", "验证码错误");
			session.removeAttribute("checkcode");
			request.getRequestDispatcher("/login.jsp").forward(request,
					response);
		} else {
			// 登陆成功
			session.setAttribute("username", "张三");
			session.removeAttribute("checkcode");
			response.sendRedirect("/web06_session/welcome.jsp");
		}
	} else {
		request.setAttribute("error", "验证码失效");
		request.getRequestDispatcher("/login.jsp").forward(request,
				response);
	}
}

六:使用Session解决表单重复提交

网路延时场景

  • 场景1 : 网络延时 ,用户可能会点击多次提交按钮服务器会多次处理多次请求
  • 场景2 :提交之后 用户点击了刷新按钮
  • 场景3 : 点击 [后退] 回到了上个表单页面再次点击提交

解决方案:场景1 : 网络延时,用户可能会点击多次提交按钮。前端js解决;

	<script type="text/javascript">
		var isCommit = ture;//表示表单可以提交
	
		function doSubmit() {
			if (isCommit) {
				isCommit = false;
				return false;
			}
			return false;
		}
	</script>

并不能解决场景2和场景3

只能依靠服务器端解决,使用Session解决

流程: 在服务器生成一个随机唯一标识(Token 令牌) ,同时把它存入session域 , 需要服务器将其发送给客户端 ,客户端发送请求是携带Token 服务器端在验证过程中 先要验证Token是否和session中的Token一致 (如果一致就可以提交 ,不一致 ,表示就是重复提交 服务器就不处理 )并且提交后需要清除session中的Token :

不一致的情况:

  • session中的Token和客户端提交的Token 不一致
  • 客户端没有携带Token
  • 服务端没有Token

1.创建一个Token

public class TokenUtil {
private TokenUtil() {

}

private static final TokenUtil tokenutil = new TokenUtil();
private static final BASE64Encoder bASE64Encoder = new BASE64Encoder();

public static TokenUtil getTokenUtil() {

	return tokenutil;
}

public String makeToken() {
	String Token = System.currentTimeMillis() + new Random().nextInt(999999999) + "";
	return bASE64Encoder.encode(Token.getBytes());

	}
}

创建一个令牌,将token存放在session

protected void doGet(HttpServletRequest request,
		HttpServletResponse response) throws ServletException, IOException {
	// 创建一个令牌
	String token = TokenUtil.getTokenUtil().makeToken();
	// 将token存放在session
	request.getSession().setAttribute("token", token);
	request.getRequestDispatcher("/form.jsp").forward(request, response);
}

2.前端jsp页面演示表单提交

	<%@ page language="java" contentType="text/html; charset=utf-8"
		pageEncoding="utf-8"%>
	<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
	<html>
	<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	<title>Insert title here</title>
	<script type="text/javascript">
		var isCommit = ture;//表示表单可以提交
	
		function doSubmit() {
			if (isCommit) {
				isCommit = false;
				return false;
			}
			return false;
		}
	</script>
	
	</head>
	<body>
		<form action="/web06_session/formTokenServlet" method="post"
			onsubmit="return doSubmit">
			用户名<input type="text" name="username" /><br /> 密 &nbsp;&nbsp;码<input
				type="password" name="password" /><br /> <input name="token"
				value="<%=session.getAttribute("token")%>" type="hidden" /> <input
				type="submit" />
		</form>
	
	</body>
	</html>

3.创建一个Servlet判断表单是否重复提交

protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {

	// 解决表单是否重复提交
	// 是否重复提交
	boolean isrepeatSubmit = isrepeatSubmit(request);
	if (!isrepeatSubmit) {
		System.out.println("表单重复提交");
	} else {
		request.getSession().removeAttribute("token");
		System.out.println("用户每一次提交需要处理");
	}

}

private boolean isrepeatSubmit(HttpServletRequest request) {
	String clientToken = request.getParameter("token");
	if (clientToken == null) {
		return false;
	}
	// 获取服务器
	String sessionToken = (String) request.getSession().getAttribute(
			"token");
	if (sessionToken == null) {
		return false;
	}
	if (!sessionToken.equals(clientToken)) {
		return false;
	}

	return true;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值