1.session案例:防止表单重复提交
JS语言写的防止客户意外提交表单(比如网速不给力时,客户多次点提交按钮)
Html代码:
用户:
这样编程的不足:但用户单击“刷新”,或单击“后退”再次提交表单,将导致表单重复提交
2. 由于上面所说的弊端,有了新的检验编程,用servlet类编写
l 表单页面由servlet程序生成,servlet为每次产生的表单页面分配一个唯一的随机标识号,并在FORM表单的一个隐藏字段中设置这个标识号,同时在当前用户的Session域中保存这个标识号。
l 当用户提交FORM表单时,负责处理表单提交的serlvet得到表单提交的标识号,并与session中存储的标识号比较,如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。
l 在下列情况下,服务器程序将拒绝用户提交的表单请求:
ü 当前用户的Session中不存在表单标识号
ü 用户提交的表单数据中没有标识号字段
ü 存储Session域中的表单标识号与表单提交的标识号不同
3. MD5算法
4.BASE64编码
l BASE64编码规则将一组连续的字节数据按6个bit位进行分组,然后对每组数据用一个ASCII字符来表示。6个bit位最多能表示26=64个数值,因此可以使用64个ASCII字符来对应这64个数值,这64个ASCII字符为:
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
l 计算[0110,0001] [0110,0010] [0110,0011]的BASE64编码
[0110,0001] [0110,0010] [0110,0011]à[0110,00] [01,0110,] [0010,01] [10,0011]
[0110,00] [01,0110,] [0010,01] [10,0011] à [24]10 [22]10 [9]10 [35]10
[24]10 [22]10 [9]10 [35]10 à "YWJj"
l BASE64编码要求把3个8位字节(即24个bit)的数据转化为4个6位字节(也是24个bit)的数据,如果原来的8位字节数据的字节个数不能被3整除,那么如何对余下的1个或2个8位字节数据进行处理呢?
仍然按6个bit位对剩余的字节进行分组,在最后不够6个bit位的内容后面添加几个为0的bit位来凑成6个bit位,例如,[0110,0001] à [0110,00] [01,0000]
l 如果编码后的整个结果文本的字符个数不是4的整数倍,那么需要在最后填充“=”字符来凑成4的倍数。
l 经过BASE64编码后的结果所占用的字节个数大约是原始内容的4/3倍,计算公式为:编码后的大小 = ((原始大小+2)/3)*4 。
5.session案例:一次性校验码
l 一次性验证码的主要目的就是为了限制人们利用工具软件来暴力猜测密码。
l 服务器程序接收到表单数据后,首先判断用户是否填写了正确的验证码,只有该验证码与服务器端保存的验证码匹配时,服务器程序才开始正常的表单处理流程。
l 密码猜测工具要逐一尝试每个密码的前题条件是先输入正确的验证码,而验证码是一次性有效的,这样基本上就阻断了密码猜测工具的自动地处理过程。
验证码案例:(红色代码是与servlet类连接所需)
packagecom.session;
importjava.awt.Color;
importjava.awt.Font;
importjava.awt.Graphics;
importjava.awt.Graphics2D;
importjava.awt.image.BufferedImage;
importjava.io.IOException;
importjava.util.Random;
importjavax.imageio.ImageIO;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
publicclass CheckCode extends HttpServlet {
private static final int WIDTH = 130;
private static final int HEIGHT = 30;
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException {
// 1.创建图片
BufferedImage image = newBufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB);
// 2.得到图片
Graphics g = image.getGraphics();
// 3 对图片进行绘制
// a.设置图片的背景色
setBackGround(g);
// c.添加干扰线
setRandomLine(g);
// g.向图形中写数据
String checkcode =setRandomNum(g);
request.getSession().setAttribute("imgcode",checkcode);
// 4.把图片写给浏览器
response.setContentType("image/jpeg");
// 告诉浏览器不要缓存
response.setHeader("Pragma","no-cache");
response.setHeader("Cache-Control","no-cache");
response.setIntHeader("Expires",-1);
ImageIO.write(image, "JPEG",response.getOutputStream());
}
private String setRandomNum(Graphics g) {
g.setFont(new Font("宋体", Font.BOLD,25));
Random random = new Random();
StringBuffer sb = new StringBuffer();
int x = 10;
for (int i = 0; i < 4; i++) {
// 产生随机数
String str = String.valueOf(random.nextInt(10));
sb.append(str);
g.setColor(newColor(random.nextInt(255), random.nextInt(255),
random.nextInt(255)));
int degree = random.nextInt() % 30;
((Graphics2D) g).rotate(degree * Math.PI /180, x, 20);
g.drawString(str, x, 20);
((Graphics2D) g).rotate(-degree * Math.PI/ 180, x, 20);
x += 30;
}
return sb.toString();
}
private void setRandomLine(Graphics g) {
g.setColor(Color.green);
Random random = new Random();
for (int i = 0; i < 5; i++) {
int x1 = random.nextInt(WIDTH);
int y1 = random.nextInt(HEIGHT);
int x2 = random.nextInt(WIDTH);
int y2 = random.nextInt(HEIGHT);
g.drawLine(x1, y1, x2, y2);
}
}
private void setBackGround(Graphics g) {
g.setColor(Color.WHITE);
g.fillRect(0, 0, WIDTH, HEIGHT);
}
public void doPost(HttpServletRequestrequest, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
验证码判断:
String checkcode =request.getParameter("checkcode");
String imgcode = (String) request.getSession().getAttribute("imgcode");
//验证码判断
if (checkcode !=null && imgcode!=null && checkcode.equals(imgcode)) {
}else{输出验证码错误}
6. 表单提交案例:
package com.repeated;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
import sun.misc.BASE64Encoder;
publicclass Token {
//构造方法私有化
private Token(){
}
publicstaticfinal Tokenentity =new Token();
publicstaticTokengetEntity(){
returnentity;
}
public String generaToken(){
String token = System.currentTimeMillis() +new Random().nextInt()+"";
try {
//运用MD5算法
MessageDigest md = MessageDigest.getInstance("md5");
byte[] md5 = md.digest(token.getBytes());
//用base64编码转换
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(md5);
} catch (NoSuchAlgorithmException e) {
thrownew RuntimeException(e);
}
}
}
packagecom.repeated;
importjava.io.IOException;
importjava.io.PrintWriter;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
publicclass Form extends HttpServlet {
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter pw = response.getWriter();
Token t = Token.getEntity();
String token = t.generaToken();
request.getSession().setAttribute("token",token);
pw.print("");
}
public void doPost(HttpServletRequestrequest, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
packagecom.repeated;
importjava.io.IOException;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importjavax.swing.JOptionPane;
publicclass FormDel extends HttpServlet {
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
boolean flag = checkToken(request);
if(!flag){
JOptionPane.showMessageDialog(null,"不能重复提交数据!!!");
request.getRequestDispatcher("./Form").forward(request,response);
return;
}
request.removeAttribute("token");
response.getWriter().println("注册成功!!!");
}
private boolean checkToken(HttpServletRequestrequest) {
String clientToken =request.getParameter("token");
String ServiceToken = (String)request.getSession().getAttribute("token");
if(clientToken == null){
returnfalse;
}
if(ServiceToken == null){
returnfalse;
}
if(clientToken.equals(ServiceToken)){
returnfalse;
}
return true;
}
public void doPost(HttpServletRequestrequest, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}