Servlet处理表单重复提交and利用referer防盗链and实现request包含页面
2012-12-10 14:45
716 查看
首先是web.xml
[html]
view plaincopyprint?
<?xml
version="1.0"
encoding="UTF-8"?>
<web-app
version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>FormServlet</servlet-name>
<servlet-class>com.jadyer.servlet.FormServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FormServlet</servlet-name>
<url-pattern>/servlet/FormServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>form.jsp</welcome-file>
</welcome-file-list>
</web-app>
然后是表单页面form.jsp
[html]
view plaincopyprint?
<%@ page language="java"
pageEncoding="UTF-8"%>
<%@ page import="com.jadyer.util.DataCoderUtil"%>
<%
//生成表单令牌
session.setAttribute("myToken", DataCoderUtil.generateToken());
//request包含页面:也可以使用这种方式,把页面包含进来
//request.getRequestDispatcher("/form.jsp").include(request, response);
%>
<form
action="<%=request.getContextPath()%>/servlet/FormServlet"
method="POST">
<input
type="hidden"
name="myToken"
value="${myToken}">
用户:<input
type="text"
name="username"><br/>
密码:<input
type="password"
name="password"><br/>
<input
type="submit"
value="提交">
</form>
下面是用于生成表单令牌的工具类DataCoderUtil.java
[java]
view plaincopyprint?
package com.jadyer.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
import sun.misc.BASE64Encoder;
/**
* DataCoderUtil
* @see ========================================================================================
* @see 这里的generateToken()是处理表单重复提交时,创建的表单令牌生成器,其返回经MD5和base64加密后的String
* @see ========================================================================================
* @see Java中每个数据都有一个摘要,即数据指纹。无论这个数据有多大,它的指纹都是固定的128位,即16个字节
* @see 我们可以使用Java中提供的java.security.MessageDigest工具类,得到随机数的数据摘要,即数据指纹
* @see ========================================================================================
* @see 全新算法:base64编码
* @see 任何数据经base64算法编码后,都会返回明文的字符串。该算法有一个特点:它会把每三个字节,都变成四个字节
* @see 比如00110010.11001101.00101001会被变成00001100.00101100.00110100.00101001
* @see 也就是把原来的24Bit平均分为四份,然后在每一份前面补两个零,以此凑成32Bit,即四个字节
* @see 故,改变之后的四个字节,每个字节的最小值就是00000000,最大值就是00111111,即最小为零,最大为63
* @see 所以,经过base64算法编码后,每个字节的最大值都不会超过64
* @see 最后,base64算法会查询它自己定制的码表,该码表记录的是0--63所对应键盘上的明文字符,最后将其返回
* @see ========================================================================================
* @author 宏宇
* @create Mar 6, 2012 2:38:04 AM
*/
public class DataCoderUtil {
public static String generateToken() {
String myToken = System.currentTimeMillis() +
new Random().nextInt() + "";
try {
byte[] myTokenMD5 = MessageDigest.getInstance("md5").digest(myToken.getBytes());
//MD5算法加密
return
new BASE64Encoder().encode(myTokenMD5);
//base64算法加密,最后返回
} catch (NoSuchAlgorithmException e) {
throw
new RuntimeException(e);
}
}
}
最后是用于处理表单请求的FormServlet.java
[java]
view plaincopyprint?
package com.jadyer.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class FormServlet
extends HttpServlet {
private static
final long serialVersionUID = -3435386674549645942L;
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* 利用referer防盗链
* @see 客户端访问时,只认可以http://127.0.0.1为首的URL
*/
String referer = request.getHeader("referer");
if(null==referer || !referer.startsWith("http://127.0.0.1")){
response.sendRedirect("/index.jsp");
return;
//如果没有这行代码,那么重定向之后,下面的代码仍会执行
}
/**
* 判断表单重复提交
* @see 思路:详见我的另一篇文章http://blog.csdn.net/jadyer/article/details/6174095
*/
if(!isTokenValid(request, response)){
System.out.println("请不要重复提交表单...");
return;
}
request.getSession().removeAttribute("myToken");
System.out.println("向数据库中注册用户...");
}
/**
* 判断表单令牌是否有效
*/
private boolean isTokenValid(HttpServletRequest request, HttpServletResponse response){
String client_token = request.getParameter("myToken");
String server_token = (String)request.getSession().getAttribute("myToken");
if(null == client_token){
return
false;
}
if(null == server_token){
return false;
}
if(!client_token.equals(server_token)){
return
false;
}
return true;
}
}
[html]
view plaincopyprint?
<?xml
version="1.0"
encoding="UTF-8"?>
<web-app
version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>FormServlet</servlet-name>
<servlet-class>com.jadyer.servlet.FormServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FormServlet</servlet-name>
<url-pattern>/servlet/FormServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>form.jsp</welcome-file>
</welcome-file-list>
</web-app>
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <servlet> <servlet-name>FormServlet</servlet-name> <servlet-class>com.jadyer.servlet.FormServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>FormServlet</servlet-name> <url-pattern>/servlet/FormServlet</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>form.jsp</welcome-file> </welcome-file-list> </web-app>
然后是表单页面form.jsp
[html]
view plaincopyprint?
<%@ page language="java"
pageEncoding="UTF-8"%>
<%@ page import="com.jadyer.util.DataCoderUtil"%>
<%
//生成表单令牌
session.setAttribute("myToken", DataCoderUtil.generateToken());
//request包含页面:也可以使用这种方式,把页面包含进来
//request.getRequestDispatcher("/form.jsp").include(request, response);
%>
<form
action="<%=request.getContextPath()%>/servlet/FormServlet"
method="POST">
<input
type="hidden"
name="myToken"
value="${myToken}">
用户:<input
type="text"
name="username"><br/>
密码:<input
type="password"
name="password"><br/>
<input
type="submit"
value="提交">
</form>
<%@ page language="java" pageEncoding="UTF-8"%> <%@ page import="com.jadyer.util.DataCoderUtil"%> <% //生成表单令牌 session.setAttribute("myToken", DataCoderUtil.generateToken()); //request包含页面:也可以使用这种方式,把页面包含进来 //request.getRequestDispatcher("/form.jsp").include(request, response); %> <form action="<%=request.getContextPath()%>/servlet/FormServlet" method="POST"> <input type="hidden" name="myToken" value="${myToken}"> 用户:<input type="text" name="username"><br/> 密码:<input type="password" name="password"><br/> <input type="submit" value="提交"> </form>
下面是用于生成表单令牌的工具类DataCoderUtil.java
[java]
view plaincopyprint?
package com.jadyer.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
import sun.misc.BASE64Encoder;
/**
* DataCoderUtil
* @see ========================================================================================
* @see 这里的generateToken()是处理表单重复提交时,创建的表单令牌生成器,其返回经MD5和base64加密后的String
* @see ========================================================================================
* @see Java中每个数据都有一个摘要,即数据指纹。无论这个数据有多大,它的指纹都是固定的128位,即16个字节
* @see 我们可以使用Java中提供的java.security.MessageDigest工具类,得到随机数的数据摘要,即数据指纹
* @see ========================================================================================
* @see 全新算法:base64编码
* @see 任何数据经base64算法编码后,都会返回明文的字符串。该算法有一个特点:它会把每三个字节,都变成四个字节
* @see 比如00110010.11001101.00101001会被变成00001100.00101100.00110100.00101001
* @see 也就是把原来的24Bit平均分为四份,然后在每一份前面补两个零,以此凑成32Bit,即四个字节
* @see 故,改变之后的四个字节,每个字节的最小值就是00000000,最大值就是00111111,即最小为零,最大为63
* @see 所以,经过base64算法编码后,每个字节的最大值都不会超过64
* @see 最后,base64算法会查询它自己定制的码表,该码表记录的是0--63所对应键盘上的明文字符,最后将其返回
* @see ========================================================================================
* @author 宏宇
* @create Mar 6, 2012 2:38:04 AM
*/
public class DataCoderUtil {
public static String generateToken() {
String myToken = System.currentTimeMillis() +
new Random().nextInt() + "";
try {
byte[] myTokenMD5 = MessageDigest.getInstance("md5").digest(myToken.getBytes());
//MD5算法加密
return
new BASE64Encoder().encode(myTokenMD5);
//base64算法加密,最后返回
} catch (NoSuchAlgorithmException e) {
throw
new RuntimeException(e);
}
}
}
package com.jadyer.util; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Random; import sun.misc.BASE64Encoder; /** * DataCoderUtil * @see ======================================================================================== * @see 这里的generateToken()是处理表单重复提交时,创建的表单令牌生成器,其返回经MD5和base64加密后的String * @see ======================================================================================== * @see Java中每个数据都有一个摘要,即数据指纹。无论这个数据有多大,它的指纹都是固定的128位,即16个字节 * @see 我们可以使用Java中提供的java.security.MessageDigest工具类,得到随机数的数据摘要,即数据指纹 * @see ======================================================================================== * @see 全新算法:base64编码 * @see 任何数据经base64算法编码后,都会返回明文的字符串。该算法有一个特点:它会把每三个字节,都变成四个字节 * @see 比如00110010.11001101.00101001会被变成00001100.00101100.00110100.00101001 * @see 也就是把原来的24Bit平均分为四份,然后在每一份前面补两个零,以此凑成32Bit,即四个字节 * @see 故,改变之后的四个字节,每个字节的最小值就是00000000,最大值就是00111111,即最小为零,最大为63 * @see 所以,经过base64算法编码后,每个字节的最大值都不会超过64 * @see 最后,base64算法会查询它自己定制的码表,该码表记录的是0--63所对应键盘上的明文字符,最后将其返回 * @see ======================================================================================== * @author 宏宇 * @create Mar 6, 2012 2:38:04 AM */ public class DataCoderUtil { public static String generateToken() { String myToken = System.currentTimeMillis() + new Random().nextInt() + ""; try { byte[] myTokenMD5 = MessageDigest.getInstance("md5").digest(myToken.getBytes()); //MD5算法加密 return new BASE64Encoder().encode(myTokenMD5); //base64算法加密,最后返回 } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } } }
最后是用于处理表单请求的FormServlet.java
[java]
view plaincopyprint?
package com.jadyer.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class FormServlet
extends HttpServlet {
private static
final long serialVersionUID = -3435386674549645942L;
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* 利用referer防盗链
* @see 客户端访问时,只认可以http://127.0.0.1为首的URL
*/
String referer = request.getHeader("referer");
if(null==referer || !referer.startsWith("http://127.0.0.1")){
response.sendRedirect("/index.jsp");
return;
//如果没有这行代码,那么重定向之后,下面的代码仍会执行
}
/**
* 判断表单重复提交
* @see 思路:详见我的另一篇文章http://blog.csdn.net/jadyer/article/details/6174095
*/
if(!isTokenValid(request, response)){
System.out.println("请不要重复提交表单...");
return;
}
request.getSession().removeAttribute("myToken");
System.out.println("向数据库中注册用户...");
}
/**
* 判断表单令牌是否有效
*/
private boolean isTokenValid(HttpServletRequest request, HttpServletResponse response){
String client_token = request.getParameter("myToken");
String server_token = (String)request.getSession().getAttribute("myToken");
if(null == client_token){
return
false;
}
if(null == server_token){
return false;
}
if(!client_token.equals(server_token)){
return
false;
}
return true;
}
}
相关文章推荐
- Servlet处理表单重复提交and利用referer防盗链and实现request包含页面
- springMVC处理表单重复提交,包含页面多个嵌套提交的情况,自定义token处理
- Html表单提交到Servlet输出到页面乱码 Html使用的编码是UTF-8编码显示页面,之后使用form表单提交字段到Servlet中,Servlet将利用getParamer方法获得fo
- 【分享】利用decorator实现Django表单防重复提交
- 如何利用Axis2+Spring实现文件上传(支持jsp页面的form表单提交),Android客户端调用
- JQuery -AJAX- html中提交表单并实现不跳转页面处理返回值
- ASP如何利用XMLHTTP实现表单的提交以及cookies或session的发送和Referer
- 利用iframe实现提交表单是页面部分刷新
- 利用decorator实现Django表单防重复提交
- Servlet、SPringMVC、Struts等防止表单重复提交的多种处理方法
- struts2利用token和tokenSession实现防止表单重复提交的具体代码
- 用Servlet处理表单提交的数据,然后再jsp页面中显示
- html中提交表单并实现不跳转页面处理返回值
- 在JSP表单提交中怎样在Servlet中处理文件上传并且获取JSP页面传过来的一些参数
- servlet_request使用referer,实现防盗链
- 拦截器springmvc防止表单重复提交【3】3秒后自动跳回首页【重点明白如何跳转到各自需要的页面没有实现 但是有思路】
- JSP表单提交给Servlet处理后,转到重定向的页面时,布局混乱
- servlet_request实现页面包含
- html中提交表单并实现不跳转页面处理返回值