表单本地安全提交

【安全提交表单数据的方法】
为 了保证安全性,在解答中,将用户所提交的字符串值首先进行编码,这样字符串中所有的“<”和“>”标记将失效,为了能使部分HTML标记生 效,可以利用替换的方法,将部分HTML标记恢复。这种方法使用非常简单,在保证了安全性的同时,允许用户输入部分HTML标记。
 
 
 

 
【HTML表单的提交方式】
HTML表单的提交方式: 两个重要的属性 action  和 method
(1) action 属性指明当前表单提交后由哪个程序来处理,这个处理程序可以是任何动态网页
(2) method 属性指明form表单的提交方式,它有两个可能的值: get 和  post
1.  get 和  post 有以下的区别:
一:  以get 方式提交的表单地址栏中会显示参数名和参数值;而post方式不会,用post提交参数相对更隐秘些,也相对更安全些。
二: 由于浏览器地址栏中能输入的最大字节数有限,所以用get方式提交不能处理参数值更大的表单,而post方式则没有这个限制。
 

【html表单提交的几种方法】 原文地址: http://www.ijser.cn/?p=34

最普通最常用最一般的方法就是用submit type..看代码:  
<form name=”form” method=”post” action=”#">  
<input type=”submit” name=”submit” value=”提交">  
</form> 

另外,还有一种常用的方法是使用图片:  
<form name=”form” method=”post” action=”# ">  
<input type=”image” name=”submit” src=”btnSubmit.jpg”>  
</form> 

第三种是使用链接来提交表单,用到了javascript的DOM模型:  
<form name=”form” method=”post” action=”#”>  
<a href=”javascript:form.submit();”>提交</a>  
</form>  
这种方法实际上是调用了一个javascript函数,使用javacript函数来提交表单,方法就非常多非常灵活了,比如可以把它加入到任意一个标签的onclick事件中:  
<form name=”form” method=”post” action=”#”>  
<div onclick=”javascript:form.submit();”>  
<span>提交</span>  
</div>  
</form> 

但是,如果一个表单里有需要有多个提交按钮怎么办呢?  
比如一个表单里的提交按钮所指向的处理页面不同,这样由于表单在定义的时候就已经确定下表单数据的处理页面,所以单纯地在表单里放多个提交按钮是没有办法达到目的的。这就需要javascript。  
首先定义一个函数:  
<script language=javascript>  
function query(){  
form.action=”query.php”;  
form.submit();}  

function update(){  
form.action=”update.php”;  
form.submit();}  
</script>  
通过javascript改变form的action属性值,这样就可以实现多提交按钮而且功能不同了,页面内代码如下:  
<form name=”form” method=”post” action=”#”>  
<input type=”button” name=”query” onclick=”query();” value=”查询”>  
<input type=”button” name=”update” onclick=”update();” value=”更新”>  
</form>  
上面一段代码,使用的是普通的按钮,而提交功能的实现方法是在它的onclick事件中调用javascript函数.  

有了上面这几种提交表单的方法,我想差不多够应付复杂的表单了。

【如何防止FORM表单本地提交?】【防止form表单重复提交】
把当前页面表单页面 HTML代码下载到本地,然后存为HTML。要知道提交的ACTION地址 就可以在本地提交。
 
添加验证字段,判断是否同一授权人提交的。对表单资格的许可。
 

【如何防止Form页面重复提交】
服务器端验证 提交页面的来源 Request.Headers.Get("referer");,如果不是本站过来的就不允许提交。
 
加一个令牌,通过判断令牌的值来判断是不是属于重复提交。
 
设置页面过期,后退后,页面失效。
 
form建立的时候,生成一个session。
session.formuuid = "一个随机数"
<form>
   <input type="hidden" value="<%=session.formuuid%>">
</form>
提交后,判断request("formuuid")和session.formuuid是否一致。
if request("formuuid") = session.formuuid then
 '处理过程
  session.formuuid = "另外一个新的随机数"
end if
 
利用Session防止表单提交
 1、产生页面时,服务器为每次产生的Form分配唯一的随机标识号,并且在form的一个hidden隐藏字段中设置这个标识号,同时在当前用户的Session中保存这个标识号。
 2、当提交表单时,服务器比较hidden和session中的标识号是否相同,相同则继续,处理完后清空Session,否则服务器忽略请求。
 
恶意用户可利用这一性质,不断重复访问页面,以致Session中保存的标识号不断增多,最终严重消耗服务器内存。  因此一些网站通常采用在Session中记录用户发帖的时间,然后通过一个时间间隔来限制用户连续发帖的数量。

【表单提交过一次以后如何防止刷新页面重新提交表单】【  http://bbs.csdn.net/topics/390746779?page=1 】
——客户端异步处理,然后再回写个东西给隐藏域。提交的时候先判断隐藏域,是否已经可以提交。
——重定向其他页面。

【防止页面多次刷新提交表单(转)】【http://ywj-sh110-163-com.iteye.com/blog/732419
当用户从表单处完成递交,如无问题已将注册信息写入数据库,但有问题的是,如何防止用户刷新页面,这相当于将原有的信息再次写入数据库,在网络上寻找解决方法,试用后将本人认为最管用的方法记下。
 
网络中给出如下解决方式:
第一种:禁用提交按钮
当用户提交表单后,使用JAVASCRIPT脚本语言,将提交钮禁用。
分析:如客户端没有开启脚本功能就出现问题;这也仅是在表单处理前有用,防止用户多次点击提交钮;现在很多网站都  启用验证码解决此问题了。
 
第二种:使用 Session
在第一次写入数据库代码后,  将Session标记;在数据库代码前判断Session是否曾经标记过并与刚才的标记是否相等。
代码:
Session("User") = True
   Response.write "您刚才已经注册过了……"
Else
   ...... '省略写入数据库部分
   Session("User") = True
End if
分析:比较管用的;但Session默认时效为20分钟,虽然可以设置时效长度,但由于网站服务器设置不同,也许达不到理想效果。
 
第三种:重新定向
注册完毕后直接将网页重新定向到其他页面。
代码:Response.Redirect "Index.html"
分析:使用此方法,需要  配合客户端脚本清除历史(history)才行,没有试用,因为用户可以使用后退按钮,继续刷新。
 
第四种:  禁止缓存
在写入数据一页最下边添加下面的代码,然后导向新页,可以  使用户点击后退按钮后,页面提示网页过期
代码:
ASP:
Response.Buffer = True    
Response.ExpiresAbsolute = Now() - 1    
Response.Expires = 0    
Response.CacheControl = "no-cache"
ASP.NET:
Response.Buffer=true;
Response.ExpiresAbsolute=DateTime.Now.AddSeconds(-1);
Response.Expires=0;
Response.CacheControl="no-cache";
分析:试用后,发现一个问题,虽然表面看到网页过期字样,但在过期网页上刷新,仍可以再次刷新多次注册。
 
第五种:用弹出窗口
提交表单的时候弹出新窗口(在新窗口页面完成数据库的写入),关闭本窗口。对于window.open()打开的窗口是无法用后退按钮的。
 
第六种:调数据库进行对比
这一种是得不偿失的方法,因为会加重服务器的负担,如果在表单没有进行AJAX方式的验证,这也算是一种必要的方法。
代码:(假设已连接数据库)
Dim Rs,SQL,UserId
UserId = Request("Userid") '从表单从取数据内容
If UserId <> "" then '不为空的时候
Set Rs=Server.CreateObject("Adodb.Recordset")
   SQL = "Select Userid From 表 Where Userid='"& UserId &"'"
   Rs.Open Sql, Conn, 2, 2
 
If Rs.Eof And Rs.Bof Then
   Response.Write "没有相同数据!"
Else
   Response.Write "有相同数据!"
End If
 
   Rs.Close
   Set Rs = Nothing
   Response.End
End If
 
经过测试,如果不想太费事,直接用第六种方法,用户刷一次就对数据库检索一次,这种方式最大的弊端就是有可能把服务器累死;
 
由于,我采用了第二种方法,结合了第四种(效果不大),在代码最前端加入了  验证由何处来本站的函数,这样可以防止用户自己在本机模仿网站表单提交数据(hi.baidu.com/76512/blog/item/b8d9be8f168d3aedf01f3680.html),也可以防止用户在本站直接在网址末端加变量值刷新数据。
 
由于在表单处已加入随机验证码,并已写入Session中,在处理数据前,可以先检测Session是否为空,空为已提交过了,不为空是第一次提交,在  第一次提交后将该Session清空
 
代码:
If Session("RndNum") = ""
   Response.Write "已提交过数据了呀!"
Else
...... '省略写入数据库代码
   Session("RndNum") = ""
End if
分析:  只要是从正常的途径递交的表单,Session("RndNum")的数值不会为空的。
 
从非正常途径,  Session为空!(比如说,直接打开网址,或在本机模拟表单递交,或在网址后添加变量值,是无法写入数据库的。Session默认的20分钟,清空后仍然符合逻辑。也不怕用户打开几个注册页面,来回刷新注册。

【禁用页面缓存的几种方法(静态和动态)】
1、在Asp页面首部<head>加入  
以下是引用片段:
  Response.Buffer   =   True    
  Response.ExpiresAbsolute   =   Now()   -   1    
  Response.Expires   =   0    
  Response.CacheControl   =   "no-cache"    
  Response.AddHeader   "Pragma",   "No-Cache"  
 
2、在HtML代码中加入  
以下是引用片段:
  <HEAD>    
  <META   HTTP-EQUIV="Pragma"   CONTENT="no-cache">    
  <META   HTTP-EQUIV="Cache-Control"   CONTENT="no-cache">    
  <META   HTTP-EQUIV="Expires"   CONTENT="0">    
  </HEAD>  
 
   
3、在重新调用原页面的时候在给页面传一个参数   Href="****.asp?random()"
前两个方法据说有时会失效,而第三种则是在跳转时传一个随机的参数! 因为aspx的缓存是与参数相关的,如果参数不同就不会使用缓存,而会重新生成页面,每次都传一个随机的参数就可以避免使用缓存。这个仅适用于asp&asp.net
4、在jsp页面中可使用如下代码实现无缓存:
以下是引用片段:
response.setHeader("Cache-Control","no-cache"); //HTTP 1.1
response.setHeader("Pragma","no-cache"); //HTTP 1.0
response.setDateHeader ("Expires", 0); //prevents caching at the proxy server
这些代码加在<head> </head>中间具体如下
以下是引用片段:
<head>
<%
response.setHeader("Cache-Control","no-cache"); //HTTP 1.1
response.setHeader("Pragma","no-cache"); //HTTP 1.0
response.setDateHeader ("Expires", 0); //prevents caching at the proxy server
%>
</head>
5、window.location.replace("WebForm1.aspx");  
参数就是你要覆盖的页面,replace的原理就是用当前页面替换掉replace参数指定的页面。  
这样可以防止用户点击back键。使用的是javascript脚本,举例如下:
a.html
以下是引用片段:
<html>
    <head>
        <title>a</title>      
        <script language="javascript">
            function jump(){
                window.location.replace("b.html");
            }
        </script>
    </head>
    <body>
       <a href="javascript:jump()">b</a>
   </body>
</html>  
b.html
以下是引用片段:
<html>
    <head>
        <title>b</title>      
        <script language="javascript">
            function jump(){
                window.location.replace("a.html");
            }
        </script>
    </head>
    <body>
       <a href="javascript:jump()">a</a>
   </body>
</html>  
前 4种只是清空了cache,即存储在Temporary Internet Files文件夹中的临时文件,而第五种则是使用跳转页面文件替换当前页面文件,并没有清空cache,也就是说Temporary Internet Files产生了相关的临时文件,两者搭配使用真是清空缓存,必备良药。
 

【防止非本站地址注册表单】
 
今天写程序,考虑到如果有个别用户在本机模拟表单注册网站ID,或发表贴子,怎么办?
编写如下代码,在注册页面和注册完毕的页面调用:
Function CheckPost()
Dim Server_v1,Server_v2
CheckPost = False
Server_v1 = Cstr(Request.ServerVariables("HTTP_REFERER"))
Server_v2 = Cstr(Request.ServerVariables("SERVER_NAME"))
 
If Mid(Server_v1,8,Len(Server_v2))<>Server_v2 then
   CheckPost=False
Else
   CheckPost=True
End If
End Function
然后在页面中调用:
If Not CheckPost() Then
   Response.Write "请从正确地址注册"
End if
 

【[Jsp]防止页面表单重复提交的解决方法】【  http://www.cnblogs.com/SCAU_que/articles/2009458.html】 【源代码】  
当我们写了个注册页面时候,用户完成注册并提交,用户注册的资料并录入数据库保存,最不希望出现的是在一个会话中出现多次提交的结果,我们可以通过为请求设置标记来避免此类事件的发生。   
1.为每个请求设置一个标记,当此页面是首次被请求时,生成  标记并放入session中,并且把此生成的标记的值 作为隐含标签传递到处理页面。   
2.提交表单时,跳转页面处理请求中的标记,如果  判断请求中session对象的标记和隐含标签中的值相同,处理请求,  并将session中的标记值去除

( TokenGen.java)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package com.beans;
 
import java.util.*;
import javax.servlet.http.*;
 
public class TokenGen {
    private static TokenGen instance = new TokenGen();
 
    private TokenGen() {}
 
    public static TokenGen getInstance() {
        return instance;
    }
 
    public synchronized boolean isTokenValid(HttpServletRequest request) {
        // 没有session,判为非法
        HttpSession session = request.getSession(false);
        if (session == null)
            return false;
 
        // session中不含token,
        // 说明form被提交过后执行了resetToken()清除了token
        // 判为非法
        String stoken = (String) session.getAttribute("token");
        if (stoken == null)
            return false;
 
        // request请求参数中不含token,
        // 判为非法
        String rtoken = request.getParameter("token");
        if (rtoken == null)
            return false;
 
        // request请求中的token与session中保存的token不等,判为非法
        return stoken.equals(rtoken);
    }
     
    /*
     * 重新设置token,当页面被请求后,将session中的token属性去除
     */
    public synchronized void resetToken(HttpServletRequest request)
    {
        HttpSession session = request.getSession(false);
        if (session!=null)
        {
            session.removeAttribute("token");
        }
    }
    /*
     * 为请求新建一个token标记,此标记由一个随机的double数toString形成,并把字符值存入session中
     */
     
    public synchronized void saveToken(HttpServletRequest request)
    {
        HttpSession session = request.getSession(true);
        Random rand = new Random();
        Double d = rand.nextDouble();
        session.setAttribute("token", d.toString());   
    }
}
1
 
(form.jsp) 其中加粗加红为生成token标记的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<%@ page language="java" import="com.beans.*" pageEncoding="gb2312"%>
 
 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
 <head>
 
  <title>注册页面1</title>
 
  <meta http-equiv="pragma" content="no-cache">
  <meta http-equiv="cache-control" content="no-cache">
  <meta http-equiv="expires" content="0">
  <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
  <meta http-equiv="description" content="This is my page">
 </head>
 <%
  TokenGen.getInstance().saveToken(request);
  String s = (String)session.getAttribute("token");
 %>
 <body>
  <form id="form1" name="form1" method="post" action="register.jsp">
   
   <table align="center">
   <tr>
    <td colspan="2"><br><input type="hidden" name="token" value="<%=s%>"/>
    </td>
   </tr>
    <tr>
     <td align="right">
      用户名:
     </td>
     <td>
      <input type="text" name="t1" />
     </td>
    </tr>
 
    <tr>
     <td align="right">
      密码:
     </td>
     <td>
      <input type="password" name="t2" />
     </td>
    </tr>
 
    <tr>
     <td align="right">
      确认密码:
     </td>
     <td>
      <input type="password" name="t3" />
     </td>
    </tr>
 
    <tr>
     <td align="right">
      性别:
     </td>
     <td>
      <input type="radio" name="radio" id="radio" value="boy" />
      
      <input type="radio" name="radio" id="radio2" value="gril" />
      
     </td>
    </tr>
 
    <tr>
     <td align="right">
      个人说明:
     </td>
     <td>
      <textarea name="textraea1" rows="15" cols="60"></textarea>
     </td>
    </tr>
 
    <tr>
     <td align="right">
      <input type="submit" name="button" id="button" value="提交" />
     </td>
     <td>
      <input type="reset" name="button2" id="button2" value="重置" />
     </td>
    </tr>
   </table>
  </form>
 </body>
</html>
(register.jsp)处理请求
   
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<%@ page language="java" import="com.beans.*" pageEncoding="gb2312"%>
 
 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
 
     
    <title>处理注册页面1</title>
     
 <meta http-equiv="pragma" content="no-cache">
 <meta http-equiv="cache-control" content="no-cache">
 <meta http-equiv="expires" content="0">   
 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
 <meta http-equiv="description" content="This is my page">
 <!--
 <link rel="stylesheet" type="text/css" href="styles.css">
 -->
 
  </head>
   
  <body>
   <%
    TokenGen tokenGen=TokenGen.getInstance();
    if (!tokenGen.isTokenValid(request))
    {
     out.print("这是重复提交或非法提交!");
    }
    else
    {
     // 处理请求,并执行resetToken方法,将session中的token去除
     tokenGen.resetToken(request);
    }
     
    %>
  </body>
</html>
其中还有一种是通过设置时间间隔来限制重复提交,其实现原理和上面的大同小异。
posted @ 2015-07-09 09:10  Uncle_Nucky  阅读(1089)  评论(0编辑  收藏  举报