在本文中,我们将详细介绍struts--token防止表单重复提交的各个方面,并为您提供关于源码分析的相关解答,同时,我们也将为您带来关于PHP+Session防止表单重复提交步骤详解、PHP+Ses
在本文中,我们将详细介绍struts--token防止表单重复提交的各个方面,并为您提供关于源码分析的相关解答,同时,我们也将为您带来关于PHP+Session防止表单重复提交步骤详解、PHP+Session防止表单重复提交的解决方法、PHP使用token防止表单重复提交的方法、PHP使用token防止表单重复提交的方法_PHP的有用知识。
本文目录一览:- struts--token防止表单重复提交(源码分析)(防止表单重复提交的token)
- PHP+Session防止表单重复提交步骤详解
- PHP+Session防止表单重复提交的解决方法
- PHP使用token防止表单重复提交的方法
- PHP使用token防止表单重复提交的方法_PHP
struts--token防止表单重复提交(源码分析)(防止表单重复提交的token)
表单重复提交
1、造成重复提交主要的两个原因:
(1) 一是,服务器处理时间久。当用户在表单中填完信息,点击“提交”按钮后,由于服务器反应时间过长没能及时看到响应信息,或者出于其它目的,再次点击“提交”按钮,从而导致在服务器端接收到两条或多条相同的信息。如果信息需要存储到后台数据库中,如此以来就会产生数据库操作异常提示信息,以至于给用户带来错误信息提示,从而给用户的使用带来不便。
(1) 二是,forward跳转引起的重复提交。当用户将信息提交到服务器,服务器响应采用forward方式调转到下一个页面后,此时地址栏中显示的是上个页面的URL,若刷新当前页面,浏览器会将再次提交用户先前输入的数据,就会再次出现表单重复提交的问题。当然你可以选择redirect方式跳转页面,这样就不会出现重复提交的问题;但有时为了达到某种效果或式。者出于网站安全的目的需要隐藏网页跳转,而不得不采用forward跳转方
2、 对token的简单理解:
(1) 当用户首次访问包含表单的页面时,服务器会在这次会话中创建一个session对象,并产生一个令牌值,然后将这个令牌值作为隐藏输入域的值,随表单一起发送到服务器端,同时将令牌值保存到Session中。
(2) 当用户提交页面时,服务器首先判断请求参数中的令牌值和Session中保存的令牌值是否相等,若相等,则清楚Session中的令牌值,然后执行数据处理操作。如果不相等,则提示用户已经提交过了表单,同时产生一个新的令牌值,保存到Session中。当用户重新访问提交数据页面时,将新产生的令牌值作为隐藏输入域的值。
3、应用步骤:
(1)struts.xml配置文件中添加token拦截器
<action name="doAddParameter"method="doAddParameter">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="token" />
<result name="success" type="redirect">/car/listParameter.action?calculator_product_id=${#request.calculator_product_id}</result>
<!-- 如果重复提交,跳转到。。。jsp页面 --> <result name="invalid.token" type="redirect">/ca/addParameter.action?calculator_product_id=${#request.calculator_product_id}</result>
</action>
这里面重要的代码是:<interceptor-ref name="defaultStack" />
<interceptor-ref name="token" />
(2)jsp页面中在form表单中添加<s:token></s:token>,并且在jsp头上引入<%@ taglib uri="/struts-tags" prefix="s"%>
4、源码分析:
(1)<s:token>标签在struts-tags.tld的定义:
<tag>
<name>token</name>
<tag-class>org.apache.struts2.views.jsp.ui.TokenTag</tag-class>
<body-content>JSP</body-content>
<description><![CDATA[Stop double-submission of forms]]></description>
<attribute>
<name>accesskey</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<description><![CDATA[Set the html accesskey attribute on rendered html element]]></description>
</attribute>
。。。。
注释:上面最重要的一行代码是<tag-class>org.apache.struts2.views.jsp.ui.TokenTag</tag-class>,指定标签对应的类
(2)TokenTag.java的源码:
/**
* @see Token
*/
public class TokenTag extends AbstractUITag {
private static final long serialVersionUID = 722480798151703457L;
public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) {
return new Token(stack, req, res);
}
}
注释:在这里面new Token对象。
(3)Token.java的源码:
@StrutsTag(name="token", tldTag, description="Stop double-submission of forms")
public class Token extends UIBean {
public static final String TEMPLATE = "token";
public Token(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
super(stack, request, response);
}
protected String getDefaultTemplate() {
return TEMPLATE;
}
/**
* First looks for the token in the PageContext using the supplied name (or {@link org.apache.struts2.util.TokenHelper#DEFAULT_TOKEN_NAME}
* if no name is provided) so that the same token can be re-used for the scope of a request for the same name. If
* the token is not in the PageContext, a new Token is created and set into the Session and the PageContext with
* the name.
*/
protected void evaluateExtraParams() {
super.evaluateExtraParams();
String tokenName;
Map parameters = getParameters();
(1)注释在参数map中查看是否包含name字段,假设没有
if (parameters.containsKey("name")) {
tokenName = (String) parameters.get("name");
} else {
if (name == null) {
tokenName = TokenHelper.DEFAULT_TOKEN_NAME; //(2) } else {
tokenName = findString(name);
if (tokenName == null) {
tokenName = name;
}
}
addParameter("name", tokenName);
}
String token = buildToken(tokenName);
addParameter("token", token);//(3)保存Token
addParameter("tokenNameField", TokenHelper.TOKEN_NAME_FIELD);
}
/**
* This will be removed in a future version of Struts.
* @deprecated Templates should use $parameters from now on, not $tag.
*/
public String getTokenNameField() {
return TokenHelper.TOKEN_NAME_FIELD;
}
(4)创建Token
private String buildToken(String name) {
Map context = stack.getContext();
Object myToken = context.get(name);
if (myToken == null) {
myToken = TokenHelper.setToken(name);
context.put(name, myToken);
}
return myToken.toString();
}
}
(4)TokenHelper.setToken(name)
public static String setToken(String tokenName) {
Map session = ActionContext.getContext().getSession();
String token = generateGUID();
try {
session.put(tokenName, token);
}
catch(IllegalStateException e) {
// WW-1182 explain to user what the problem is
String msg = "Error creating HttpSession due response is commited to client. You can use the CreateSessionInterceptor or create the HttpSession from your action before the result is rendered to the client: " + e.getMessage();
LOG.error(msg, e);
throw new IllegalArgumentException(msg);
}
return token;
}
注释:产生一个UUID,并且保存到session中.
上面的步骤中Token已经创建好了,并且保存到了session中,现在我们看看拦截器是怎么处理的?
(5)Struts2的内置拦截器<interceptor name="token"/>
中TokenInterceptor.java 的源码:
* @see TokenSessionStoreInterceptor
* @see TokenHelper
*/
public class TokenInterceptor extends MethodFilterInterceptor {
private static final long serialVersionUID = -6680894220590585506L;
public static final String INVALID_TOKEN_CODE = "invalid.token";
/**
* @see com.opensymphony.xwork2.interceptor.MethodFilterInterceptor#doIntercept(com.opensymphony.xwork2.ActionInvocation)
*/
protected String doIntercept(ActionInvocation invocation) throws Exception {
if (log.isDebugEnabled()) {
log.debug("Intercepting invocation to check for valid transaction token.");
}
//see WW-2902: we need to use the real HttpSession here, as opposed to the map
//that wraps the session, because a new wrap is created on every request
HttpSession session = ServletActionContext.getRequest().getSession(true);
synchronized (session) {
//(1)判断Token是否有效
if (!TokenHelper.validToken()) {
(2)Token无效,返回结果invalid.token
return handleInvalidToken(invocation);
}
}
//(3)Token有效时,去做更多的处理
return handleValidToken(invocation);
}
/**
* Determines what to do if an invalid token is provided. If the action implements {@link ValidationAware}
*
* @param invocation the action invocation where the invalid token failed
* @return the return code to indicate should be processed
* @throws Exception when any unexpected error occurs.
*/
protected String handleInvalidToken(ActionInvocation invocation) throws Exception {
Object action = invocation.getAction();
String errorMessage = LocalizedTextUtil.findText(this.getClass(), "struts.messages.invalid.token",
invocation.getInvocationContext().getLocale(),
"The form has already been processed or no token was supplied, please try again.", new Object[0]);
if (action instanceof ValidationAware) {
((ValidationAware) action).addActionError(errorMessage);
} else {
log.warn(errorMessage);
}
return INVALID_TOKEN_CODE;
}
/**
* Called when a valid token is found. This method invokes the action by can be changed to do something more
* interesting.
*
* @param invocation the action invocation
* @throws Exception when any unexpected error occurs.
*/
protected String handleValidToken(ActionInvocation invocation) throws Exception {
return invocation.invoke();
}
}
(6)查看Token是否有效TokenHelper.validToken()源码:
public static boolean validToken() {
String tokenName = getTokenName();//(1)获取tokenName
if (tokenName == null) {
if (LOG.isDebugEnabled()) {
LOG.debug("no token name found -> Invalid token ");
}
return false;
}
String token = getToken(tokenName); //(2)获取token的值,注意这是页面上传来的
if (token == null) {
if (LOG.isDebugEnabled()) {
LOG.debug("no token found for token name "+tokenName+" -> Invalid token ");
}
return false;
}
//(3)在session中获取token值
Map session = ActionContext.getContext().getSession();
String sessionToken = (String) session.get(tokenName);
//(4)比较2个token是否一致
if (!token.equals(sessionToken)) {
if (LOG.isWarnEnabled()) {
LOG.warn(LocalizedTextUtil.findText(TokenHelper.class, "struts.internal.invalid.token", ActionContext.getContext().getLocale(), "Form token {0} does not match the session token {1}.", new Object[]{
token, sessionToken
}));
}
return false;
}
// remove the token so it won''t be used again
//(5)token合法,把session中的token删除
session.remove(tokenName);
return true;
}
public static String getTokenName() {
Map params = ActionContext.getContext().getParameters();
if (!params.containsKey(TOKEN_NAME_FIELD)) {
if (LOG.isWarnEnabled()) {
LOG.warn("Could not find token name in params.");
}
return null;
}
String[] tokenNames = (String[]) params.get(TOKEN_NAME_FIELD);
String tokenName;
if ((tokenNames == null) || (tokenNames.length < 1)) {
if (LOG.isWarnEnabled()) {
LOG.warn("Got a null or empty token name.");
}
return null;
}
tokenName = tokenNames[0];
return tokenName;
}
public static String getToken(String tokenName) {
if (tokenName == null ) {
return null;
}
Map params = ActionContext.getContext().getParameters();
String[] tokens = (String[]) params.get(tokenName);
String token;
if ((tokens == null) || (tokens.length < 1)) {
if (LOG.isWarnEnabled()) {
LOG.warn("Could not find token mapped to token name " + tokenName);
}
return null;
}
token = tokens[0];
return token;
}
到这里,结束了。
PHP+Session防止表单重复提交步骤详解
这次给大家带来PHP+Session防止表单重复提交步骤详解,PHP+Session防止表单重复提交的注意事项有哪些,下面就是实战案例,一起来看一下。
index.php
当前表单页面is_submit设为0
SESSION_START(); $_SESSION['is_submit'] = 0; <form id="reg" action="post.php" method="post"> <p>用户名:<input type="text"name="username" id="user"></p> <p>密 码:<input type="password"name="password" id="pass"></p> <p>E-mail:<input type="text"name="email" id="email"></p> <p><input type="submit" name="submit"value="提交注册"/></p><p><span>立即学习</span>“<a href="https://pan.quark.cn/s/7fc7563c4182"rel="nofollow" target="_blank">PHP免费学习笔记(深入)</a>”;</p> </form>
post.php
若是提交表单了,设当前''is_submit为1,若是刷新post.php,那么将执行else代码
SESSION_START(); if (isset($_POST['submit'])) { if ($_SESSION['is_submit'] == '0') { $_SESSION['is_submit'] = '1'; echo "代码块,要做的事,代码...<a onclick='history.go(-1);' href='javascript:void(0)'>返回</a>"; } else { echo "请不用重复提交<a href='index.php'>PHP+SESSION防止表单重复提交</a>"; } }
php 解决表单重复提交实现方法介绍
[导读] 重复提交是我们开发中会常碰到的一个问题,除了我们使用js来防止表单的重复提交,同时还可以使用php来防止重复提交哦。
例1 代码如下
重复提交是我们开发中会常碰到的一个问题,除了我们使用js来防止表单的重复提交,同时还可以使用php来防止重复提交哦。
例1
代码如下
<?php /* * php中如何防止表单的重复提交 */ session_start(); if (empty($_SESSION['ip'])) {//第一次写入操作,判断是否记录了IP地址,以此知道是否要写入数据库 $_SESSION['ip'] = $_SERVER['REMOTE_ADDR']; //第一次写入,为后面刷新或后退的判断做个铺垫 //...........//写入数据库操作 } else {//已经有第一次写入后的操作,也就不再写入数据库 echo '请不要再次刷新和后退'; //写一些已经写入的提示或其它东西 } ?>
具体原理
session范围变量token来防止。
1. 开启session:
session_start();
2. 如果有表单提交
代码如下 复制代码
if (isset($token))
token以hidden的形式包含在form当中。
代码如下 复制代码
<input type="hidden" name="token" value="<?php echo $token; ?>" />
3. 如果是重复提交表单
代码如下
if ($_SESSION["token"] != $token) { // 不让重复提交,在此处理 // header("location:".$_SERVER['PHP_SELF']); } else { // 正常的表单提交,在此处理 // echo "已提交"; }
4. 设置token值
代码如下
$token = mt_rand(0,1000000); $_SESSION['token'] = $token;
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
PHP实现大文件切割与合并步骤详解
PHP+mongoDB数据库操作步骤详解
php中文网学习专题:php session (包含图文、视频、案例)
以上就是PHP+Session防止表单重复提交步骤详解的详细内容,更多请关注php中文网其它相关文章!
PHP+Session防止表单重复提交的解决方法
index.php
当前表单页面is_submit设为0
SESSION_START(); $_SESSION[''is_submit''] = 0; <form id="reg" action="post.php" method="post"> <p>用户名:<input type="text"name="username" id="user"></p> <p>密 码:<input type="password"name="password" id="pass"></p> <p>E-mail:<input type="text"name="email" id="email"></p> <p><input type="submit" name="submit"value="提交注册"/></p> </form>
post.php
若是提交表单了,设当前''is_submit为1,若是刷新post.php,那么将执行else代码
SESSION_START(); if (isset($_POST[''submit''])) { if ($_SESSION[''is_submit''] == ''0'') { $_SESSION[''is_submit''] = ''1''; echo "代码块,要做的事,代码...<a onclick=''history.go(-1);'' href=''javascript:void(0)''>返回</a>"; } else { echo "请不用重复提交<a href=''index.php''>PHP+SESSION防止表单重复提交</a>"; } }
php 解决表单重复提交实现方法介绍
[导读] 重复提交是我们开发中会常碰到的一个问题,除了我们使用js来防止表单的重复提交,同时还可以使用php来防止重复提交哦。
例1 代码如下
重复提交是我们开发中会常碰到的一个问题,除了我们使用js来防止表单的重复提交,同时还可以使用php来防止重复提交哦。
例1
代码如下
<?php /* * php中如何防止表单的重复提交 */ session_start(); if (empty($_SESSION[''ip''])) {//第一次写入操作,判断是否记录了IP地址,以此知道是否要写入数据库 $_SESSION[''ip''] = $_SERVER[''REMOTE_ADDR'']; //第一次写入,为后面刷新或后退的判断做个铺垫 //...........//写入数据库操作 } else {//已经有第一次写入后的操作,也就不再写入数据库 echo ''请不要再次刷新和后退''; //写一些已经写入的提示或其它东西 } ?>
具体原理
session范围变量token来防止。
1. 开启session:
session_start();
2. 如果有表单提交
代码如下 复制代码
if (isset($token))
token以hidden的形式包含在form当中。
代码如下 复制代码
<input type="hidden" name="token" value="<?php echo $token; ?>" />
3. 如果是重复提交表单
代码如下
if ($_SESSION["token"] != $token) { // 不让重复提交,在此处理 // header("location:".$_SERVER[''PHP_SELF'']); } else { // 正常的表单提交,在此处理 // echo "已提交"; }
4. 设置token值
代码如下
$token = mt_rand(0,1000000); $_SESSION[''token''] = $token;
总结
以上所述是小编给大家介绍的PHP+Session防止表单重复提交的解决方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
- PHP实现防止表单重复提交功能【基于token验证】
- php 防止表单重复提交两种实现方法
- php表单加入Token防止重复提交的方法分析
- php解决和避免form表单重复提交的几种方法
- PHP使用token防止表单重复提交的方法
- php防止表单重复提交实例讲解
PHP使用token防止表单重复提交的方法
本文实例讲述了PHP使用token防止表单重复提交的方法。分享给大家供大家参考,具体如下:
<?php /* * PHP使用token防止表单重复提交 * 此处理方法纯粹是为了给初学者参考 */ session_start(); function set_token() { $_SESSION[''token''] = md5(microtime(true)); } function valid_token() { $return = $_REQUEST[''token''] === $_SESSION[''token''] ? true : false; set_token(); return $return; } //如果token为空则生成一个token if(!isset($_SESSION[''token'']) || $_SESSION[''token'']=='''') { set_token(); } if(isset($_POST[''test''])){ if(!valid_token()){ echo "token error"; }else{ echo ''成功提交,Value:''.$_POST[''test'']; } } ?> <form method="post" action=""> <input type="hidden" name="token" value="<?php echo $_SESSION[''token'']?>"> <input type="text" name="test" value="Default"> <input type="submit" value="提交" /> </form>
更多关于PHP相关内容感兴趣的读者可查看本站专题:《php curl用法总结》、《PHP运算与运算符用法总结》、《PHP网络编程技巧总结》、《PHP基本语法入门教程》、《php操作office文档技巧总结(包括word,excel,access,ppt)》、《php日期与时间用法总结》、《php面向对象程序设计入门教程》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》
希望本文所述对大家PHP程序设计有所帮助。
- PHP实现防止表单重复提交功能【基于token验证】
- PHP+Session防止表单重复提交的解决方法
- php 防止表单重复提交两种实现方法
- php表单加入Token防止重复提交的方法分析
- php解决和避免form表单重复提交的几种方法
- php防止表单重复提交实例讲解
PHP使用token防止表单重复提交的方法_PHP
本文实例讲述了php使用token防止表单重复提交的方法。分享给大家供大家参考,具体如下:
<?php /* * PHP使用token防止表单重复提交 * 此处理方法纯粹是为了给初学者参考 */ session_start(); function set_token() { $_SESSION[''token''] = md5(microtime(true)); } function valid_token() { $return = $_REQUEST[''token''] === $_SESSION[''token''] ? true : false; set_token(); return $return; } //如果token为空则生成一个token if(!isset($_SESSION[''token'']) || $_SESSION[''token'']=='''') { set_token(); } if(isset($_POST[''test''])){ if(!valid_token()){ echo "token error"; }else{ echo ''成功提交,Value:''.$_POST[''test'']; } } ?> <form method="post" action=""> <input type="hidden" name="token" value="<?php echo $_SESSION[''token'']?>"> <input type="text" name="test" value="Default"> <input type="submit" value="提交" /> </form>
更多关于PHP相关内容感兴趣的读者可查看本站专题:《php curl用法总结》、《PHP运算与运算符用法总结》、《PHP网络编程技巧总结》、《PHP基本语法入门教程》、《php操作office文档技巧总结(包括word,excel,access,ppt)》、《php日期与时间用法总结》、《php面向对象程序设计入门教程》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》
希望本文所述对大家PHP程序设计有所帮助。
今天关于struts--token防止表单重复提交和源码分析的讲解已经结束,谢谢您的阅读,如果想了解更多关于PHP+Session防止表单重复提交步骤详解、PHP+Session防止表单重复提交的解决方法、PHP使用token防止表单重复提交的方法、PHP使用token防止表单重复提交的方法_PHP的相关知识,请在本站搜索。
本文标签: