表单本地安全提交
【安全提交表单数据的方法】
为 了保证安全性,在解答中,将用户所提交的字符串值首先进行编码,这样字符串中所有的“<”和“>”标记将失效,为了能使部分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>
最普通最常用最一般的方法就是用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中的标记值去除。
当我们写了个注册页面时候,用户完成注册并提交,用户注册的资料并录入数据库保存,最不希望出现的是在一个会话中出现多次提交的结果,我们可以通过为请求设置标记来避免此类事件的发生。
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 > |
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 > |
其中还有一种是通过设置时间间隔来限制重复提交,其实现原理和上面的大同小异。