session 的应用——防止表单重复提交——1.0版

[size=x-large]
1). 表单的重复提交:

> 在表单页面, 多次点击 "提交" 按钮.

> 在[color=red]转发[/color]的情况下, "刷新" 在成功页面

> 点击 "后退" 后, 再次提交表单.

2). 不属于表单重复提交:

> 点击 "后退" 后,[color=red]刷新表单页面[/color] , 再次提交表单. 属于是一个新的请求

3). 思路:

> 在表单中做一个标记

> 在 Servlet 中验证标记是否存在, 若存在, 受理请求, 同时销毁标记; 若不存在, 视为重复提交

4). 步骤:

> 做标记

* 在表单中使用隐藏域: 不行! 因为在点击 "刷新" 时, 隐藏域和一般的表单域是一样的, 都会被提交到 Servlet 中.

* 放在 request 属性中: 不行! 因为 form 页面的 request 和点击 "提交" 按钮的 request 是两个不同的请求.

* 放在 session 属性中:

> 在 Servlet 中进行验证:

* 获取标记

* 检查标记是否为空, 若为空, 则按重复提交处理; 若不为空, 将其从 session 中清除, 处理表单

5). 完善:

> 在 Session 中放入的值应该是一个随机值, 且唯一: 使用当前的系统时间

> 在 Servelt 中不但要检验 Session 的值是否存在, 还要检查 Session 中的值是否和当时放的值是否一致: 把 Session 中的属性值放在隐藏域中

[/size]

代码实现:


xml 文档自己配


<%@ 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>
</head>
<body>

<%
//取得唯一值
String time = "" +session.getId() + System.currentTimeMillis() ;
session.setAttribute("token", time) ;
%>

<form action="LoginServlet" method="post">
<!-- 用隐藏域将表单做上标记 -->
<input type="hidden" name="token" value="<%=time %>"/>
<table border="1">
<tr>
<td>Name:</td>
<td>
<input type="text" name="name"/>
</td>
</tr>

<tr>
<td>Password:</td>
<td>
<input type="password" name="password"/>
</td>
</tr>

<tr rowspan="2">
<td>
<input type="submit" value="Submit"/>
</td>
<td>
<input type="reset" value="Reset"/>
</td>
</tr>
</table>
</form>

</body>
</html>



<%@ 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>
</head>
<body>

注册成功!

</body>
</html>




<%@ 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>
</head>
<body>

<h4>表单已经提交!请不要多次提交!</h4>

</body>
</html>



package com.syh.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;


public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;


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

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
//模拟网速
Thread.sleep(3000) ;
} catch (InterruptedException e) {
e.printStackTrace();
}

//0. 获取 "标记"
boolean flag = true ;

//1. 获取 HttpSession, 若 Session 不存在, 为重复提交
HttpSession session = request.getSession(false) ;
if(null == session) {
flag = false ;
}else {
//2. 从 Session 中获取指定的属性值, 若指定的值不存在, 也是为重复提交
String token = (String)session.getAttribute("token") ;
if(null == token) {
flag = false ;
}else {
//3. 从隐藏域中获取 Session 中存放的属性值, 若指定的值不存在, 也是为重复提交
String token2 = request.getParameter("token") ;
if(null == token2) {
flag = false ;
}else {
//4. 比较 token 和 token2 的值是否一致
if(token.equals(token2)) {
//5. 从 Session 中移除属性
session.removeAttribute("token") ;
}
}
}
}


if(!flag){
System.out.println("重复提交");
response.sendRedirect(request.getContextPath() + "/error.jsp") ;
return ;
}
String name = request.getParameter("name") ;
System.out.println("添加成功-->" + name);

//这里必须用转发!仔细想想就明白了!因为转发的时候,URL 没有改变!当我们再次刷新的时候,
//再次对该页面请求了!故而同一个表单再次请求了!
request.getRequestDispatcher("/success.jsp").forward(request, response) ;
//response.sendRedirect(request.getContextPath() + "/success.jsp") ;




}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Web开发中,Session是一种在服务器端存储用户数据的方式,可以在多个页面中共享这些数据。Session通常用于存储用户登录信息、购物车信息等。 在Python中,可以使用内置的`session`对象来实现Session功能。下面是一个简单的例子: ```python from flask import Flask, session, redirect, url_for, escape, request app = Flask(__name__) app.secret_key = 'my_secret_key' @app.route('/') def index(): if 'username' in session: username = session['username'] return 'Logged in as ' + username + '<br>' + \ "<b><a href = '/logout'>click here to log out</a></b>" return "You are not logged in <br><a href = '/login'></b>" + \ "click here to log in</b></a>" @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': session['username'] = request.form['username'] return redirect(url_for('index')) return ''' <form action="" method="post"> <p><input type="text" name="username"> <p><input type="submit" value="Login"> </form> ''' @app.route('/logout') def logout(): session.pop('username', None) return redirect(url_for('index')) ``` 在上面的例子中,我们使用了Flask框架来实现Web应用。在应用启动时,我们设置了一个`secret_key`,这个密钥用于保护Session数据的安全性。 在`index`函数中,我们检查了Session中是否存在`username`键。如果存在,说明用户已经登录,我们将显示用户的用户名和一个链接,可以用于退出登录。如果不存在,说明用户尚未登录,我们将显示一个登录链接。 在`login`函数中,我们检查了请求的方法是否为POST。如果是,说明用户提交了登录表单,我们将从表单中获取用户名,并将其存储到Session中。然后,我们将重定向到`index`函数中。如果请求的方法为GET,我们将显示一个包含用户名输入框和提交按钮的表单。 在`logout`函数中,我们使用`pop`方法从Session中删除`username`键。然后,我们将重定向到`index`函数中。 总之,Session是一个非常有用的工具,可以帮助我们在Web应用中存储和共享用户数据。使用Python中的`session`对象可以很容易地实现Session功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值