JAVA–利用Filter和session防止页面重复提交
JAVA–利用Filter和session防止页面重复提交
解决思路:
1 用户访问表单页面,先经过过滤器,过滤器设置一个随机id作为token令牌, 并将该token放入表单隐藏域中.
2 表单响应到浏览器,用户填充数据后提交请求;
3 请求经过过滤器,过滤器获取表单中的令牌进行验证,如果和之前生成的令牌一致,则将请求放行,并且清空令牌;
4 如果用户重复提交表单,请求经过过滤器,过滤器进行验证.因为第一次放行后令牌已经清空失效,令牌不一致,不放行.跳转到提醒界面.
需用知识:
1 过滤器基础知识
2 servlet基础知识
3 filter基础知识
4 jsp基础知识
代码实现
1 jsp实现form表单页面
<%@ 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" method="post">
<!-- 利用表单的隐藏域 保存token令牌 -->
<!-- ${token}等价于req.getsession().getAttribute("token")--> <input type="hidden" name="token" value="${token}" />
用户名:<input type="text" name="username"/><br/>
密码:<input type="password" name="password"/><br/>
<input type="submit" value="login"/>
</form>
</body>
</html>
2 filter过滤器
package com.woniu.filter.controler; import java.io.IOException;
import java.util.UUID; import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; /**
* Servlet Filter implementation class TokenFilte
*/ //过滤所有servlet
@WebFilter("*") public class TokenFilte implements Filter { public TokenFilte() {
// TODO Auto-generated constructor stub
} public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
//设置编码集
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charser=utr-8");
//向下转型
HttpServletRequest req=(HttpServletRequest) request;
HttpServletResponse resp=(HttpServletResponse) response; //获取表单的token
String parameterToken = req.getParameter("token");
//获取session中的token
String sessionToken = (String) req.getSession().getAttribute("token"); //判断表单的token,不为空说明用户已经提交form表单,需要验证是否重复提交,
//为空说明是第一次进入登录页面,需要设置token
if (parameterToken!=null) {
//判断两个令牌是否相等,相等则放行,并重置令牌
if(parameterToken.equals(sessionToken)) {
//重置令牌
req.getSession().removeAttribute("token");
chain.doFilter(request, response);
}else {//说明是重复提交,转发到提示页面
req.getRequestDispatcher("repeatReminder").forward(request, response); }
}else {//第一次进来,需要设置令牌
//生成宇宙唯一码
String token = UUID.randomUUID().toString();
//设置session
req.getSession().setAttribute("token",token);
//放行
chain.doFilter(request, response);
} } @Override
public void destroy() {
// TODO Auto-generated method stub } @Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub } }
3 表单响应的servlet
利用线程睡30秒,模拟网络拥堵
package com.woniu.filter.controler; 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; /**
* Servlet implementation class PrintUser
*/
@WebServlet("/login")
public class Login extends HttpServlet {
private static final long serialVersionUID = 1L; public Login() {
super();
// TODO Auto-generated constructor stub
} protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
//线程睡30秒,便于演示网络拥堵
Thread.sleep(30000);
response.getWriter().write("登录成功");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
} }
4 重复提交时响应的servlet
重复提交时跳转到该提醒页面
package com.woniu.filter.controler; 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; /**
* Servlet implementation class repeatReminder
*/
@WebServlet("/repeatReminder")
public class repeatReminder extends HttpServlet {
private static final long serialVersionUID = 1L;
public repeatReminder() {
super();
// TODO Auto-generated constructor stub
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("页面正在处理,请勿重复提交");
} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
} }
JAVA–利用Filter和session防止页面重复提交的更多相关文章
- PHP避免刷新页面重复提交
PHP避免刷新页面重复提交 2013-07-09 15:27 匿名 | 浏览 3567 次 编程语言 情景:从html提交数据到x.php 在x.php中$_POST数据写库并且显示,当x.php刷新 ...
- ASP.NET防止连续多次点击提交按钮 导致页面重复提交
PS:实际使用中发现,第①种方法在火狐浏览中有时候有问题.第2种方法,在各个浏览器中都没问题 近做项目遇到了这样的情况: 公司网络比平常慢了不少,在点击保存按钮提交页面后需等待挺长的一段时间,忍不住手 ...
- java struts2入门学习--防止表单重复提交.OGNL语言学习
一.知识点回顾 防止表单重复提交核心思想: 客户端和服务器端和写一个token,比较两个token的值相同,则非重复提交;不同,则是重复提交. 1.getSession三种方式比较: request. ...
- php止刷新页面重复提交
利用session来解决,首先新建一个session,并赋值,第一次提交后改变session的值,当第二次再此提交此内容时,如果不是我们的赋值,就不在处理传过来的数据.如:<?php sessi ...
- session实现防止重复提交,以及验证
参考文档 1.生成Token的参考文档.http://www.cnblogs.com/TianFang/p/3180899.html 2.主要参考文档.http://www.cnblogs.com/x ...
- c#.net防止按F5刷新页面重复提交的方法
在网上购物的过程中,提交完一个页面后,如果此时按f5刷新,则会弹出一个提示:如果继续,则会重新发送提交我们刚才提交的内容,这个问题应该规避掉,不然总是重复提交付款,那可不是件好事. 在c#.net中的 ...
- java后端使用token处理表单重复提交
保证接口幂等性,表单重复提交 前台解决方案:提交后按钮禁用.置灰.页面出现遮罩后台解决方案: 使用token,每个token只能使用一次1.在调用接口之前生成对应的Token,存放至redis 2 ...
- Token机制,防止web页面重复提交
1.业务要求:页面的数据只能被点击提交一次 2.发生原因: 由于重复点击或者网络重发,或者nginx重发等情况会导致数据被重复提交 3.解决办法: 集群环境:采用token加redis(redis单线 ...
- UseSubmitBehavior="false" 防止页面重复提交bug
OnClientClick="this.disabled=true;" UseSubmitBehavior="false" 注: 1.当设置UseSubmitB ...
随机推荐
- 小程序&app 注册登录、绑定
前段时间开发中的一款产品,有小程序和app:小程序直接微信登录,app使用手机号+验证码注册,手机号+验证码/密码登录. 用户使用其中一套账号密码即可正常使用,不强制要求完善另一套账号.为避免同一用户 ...
- MongoDB 查看当前配置
MongoDB Enterprise > db.adminCommand({getParameter:"*"}) MongoDB Enterprise > db._ad ...
- ring3 x32挂起进程注入原理.
目录 一丶挂起进程注入简介与前言 二丶ShellCode核心讲解. 2.1 保存Contex.EIP 2.2 DLL路径重定位 2.3 LoadLibrary的重定位 三丶 全部C++代码.拷贝即可使 ...
- 第一章 Electron介绍 | Electron in Action(中译)
Github 官方地址 代表作: Visual Studio Code Atom - Code editor. Github开源的代码编辑器,Electron起源地 Visual Studio Cod ...
- Android Studio 之 ViewModel
ViewModel 是 JetPack 类库中的一个功能,可以保存控件的状态 ,在整个Activity 生命周期中,状态不会失效 如屏幕翻转时,状态可保留,不会失效! 与 LiveData 配合使用! ...
- python之turtle使用:画一颗美美哒的树
关于工具介绍这里小生就不赘述了,这里附上个人觉得最详细的文档地址:https://docs.python.org/zh-cn/3/library/turtle.html?highlight=turtl ...
- mysql5.7密码过期ERROR 1862 (HY000): Your password has expired. To log in you must change
环境: ubuntu14.04 mysql5.7 一.mysql5.7 密码过期问题 报错: ERROR 1862 (HY000): Your password has expired. To lo ...
- 使用gdb调试段错误
[https://blog.csdn.net/xj9120/article/details/91380074] 1.bt 2.frame number 3.一般是内存问题 4.kill
- ping某域名的整个流程
实验环境:主机A,B(可不再同一网段),主机B有域名假设为www.baidu.com首先:1. 本地主机A在命令行下执行"ipconfig/flushdns"命令来清空本地DNS高 ...
- Spring Cloud Zuul 概览
什么是API网关 网关这个词其实是一个硬件概念.因为按照定义,网络网关出现在网络的边缘,所以防火墙和代理服务器等相关功能 往往与之集成在一起.在家庭网络 和小型企业中,宽带路由器通常充当网络网关.它将 ...