`
m635674608
  • 浏览: 4929334 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Struts2 的token原理

阅读更多

在页面加载时,<s: token />产生一个GUID(Globally Unique Identifier,全局唯一标识符)值的隐藏输入框如:

< input type ="hidden" name ="struts.token.name" value ="struts.token" />
< input type ="hidden" name ="struts.token" value ="BXPNNDG6BB11ZXHPI4E106CZ5K7VNMHR" />
同时,将GUID放到会话(session)中;在执行action之前,“token”拦截器将会话token与请求token比较,如果两者相同,则 将会话中的token删除并往下执行,否则向actionErrors加入错误信息。如此一来,如果用户通过某种手段提交了两次相同的请求,两个 token就会不同。
当加载页面的时候会调用<s: token /> 标签相应的tag
/*    */ 
/*    */ public class TokenTag extends AbstractUITag
/*    */ {
/*    */   private static final long serialVersionUID = 722480798151703457L;
/*    */ 
/*    */   public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res)
/*    */   {
/* 41 */     return new Token(stack, req, res);
/*    */   }
/*    */ }
 然后条用父类相应帮助方法
public class TokenHelper
/*     */ {
                 //默认的token名字可以自己定义
/*     */    public static final String DEFAULT_TOKEN_NAME = "struts.token";
/*     */    public static final String TOKEN_NAME_FIELD = "struts.token.name";
/*  48 */   private static final Logger LOG = LoggerFactory.getLogger(TokenHelper.class);
/*  49 */   private static final Random RANDOM = new Random();
/*     */ 
/*     */   public static String setToken()
/*     */   {
/*  58 */     return setToken("struts.token");
/*     */   }
/*     */   //当页面初始化的时候调用setToken/*     */   
          public static String setToken(String tokenName)
/*     */   {
/*  68 */     Map session = ActionContext.getContext().getSession();
/*  69 */     String token = generateGUID();
/*     */     try {
                    //放入session中,键为struts.token:值token为一个随机数值
/*  71 */       session.put(tokenName, token);
/*     */     }
/*     */     catch (IllegalStateException e)
/*     */     {
/*  75 */       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();
/*  76 */       LOG.error(msg, e, new String[0]);
/*  77 */       throw new IllegalArgumentException(msg);
/*     */     }
/*     */ 
/*  80 */     return token;
/*     */   }
/*     */   //所得token的值
/*     */   public static String getToken()
/*     */   {
/*  90 */     return getToken("struts.token");
/*     */   }
/*     */ 
/*     */   public static String getToken(String tokenName)
/*     */   {
/* 100 */     if (tokenName == null) {
/* 101 */       return null;
/*     */     }
/* 103 */     Map params = ActionContext.getContext().getParameters();
/* 104 */     String[] tokens = (String[])(String[])params.get(tokenName);
/*     */ 
/* 107 */     if ((tokens == null) || (tokens.length < 1)) {
/* 108 */       LOG.warn("Could not find token mapped to token name " + tokenName, new String[0]);
/*     */ 
/* 110 */       return null;
/*     */     }
/*     */ 
/* 113 */     String token = tokens[0];
/*     */ 
/* 115 */     return token;
/*     */   }
/*     */    //所得struts.token.name 隐藏表达欲的值 token.name
/*     */   public static String getTokenName()
/*     */   {
/* 124 */     Map params = ActionContext.getContext().getParameters();
/*     */ 
/* 126 */     if (!params.containsKey("struts.token.name")) {
/* 127 */       LOG.warn("Could not find token name in params.", new String[0]);
/*     */ 
/* 129 */       return null;
/*     */     }
/*     */ 
/* 132 */     String[] tokenNames = (String[])(String[])params.get("struts.token.name");
/*     */ 
/* 135 */     if ((tokenNames == null) || (tokenNames.length < 1)) {
/* 136 */       LOG.warn("Got a null or empty token name.", new String[0]);
/*     */ 
/* 138 */       return null;
/*     */     }
/*     */ 
/* 141 */     String tokenName = tokenNames[0];
/*     */ 
/* 143 */     return tokenName;
/*     */   }
/*     */    //验证token是否重复提交
/*     */   public static boolean validToken()
/*     */   {
/* 153 */     String tokenName = getTokenName();
/*     */ 
/* 155 */     if (tokenName == null) {
/* 156 */       if (LOG.isDebugEnabled())
/* 157 */         LOG.debug("no token name found -> Invalid token ", new String[0]);
/* 158 */       return false;
/*     */     }
/*     */         //通过tokenName获得页面初始化token的值
/* 161 */     String token = getToken(tokenName);
/*     */ 
/* 163 */     if (token == null) {
/* 164 */       if (LOG.isDebugEnabled())
/* 165 */         LOG.debug("no token found for token name " + tokenName + " -> Invalid token ", new String[0]);
/* 166 */       return false;
/*     */     }
/*     */       //获取session中的token...
/* 169 */     Map session = ActionContext.getContext().getSession();
/* 170 */     String sessionToken = (String)session.get(tokenName);
/*     */       //判断session中的token值和页面上的token值是否相等
/* 172 */     if (!token.equals(sessionToken)) {
/* 173 */       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 }), new String[0]);
/*     */ 
/* 177 */       return false;
/*     */     }
/*     */ 
/* 181 */     session.remove(tokenName);
/*     */ 
/* 183 */     return true;
/*     */   }
/*     */   //产生随机数
/*     */   public static String generateGUID() {
/* 187 */     return new BigInteger(165, RANDOM).toString(36).toUpperCase();
/*     */   }
/*     */ }

 
    当一个表单提交的时候。。。经过token拦截器。就相当于filter.Spring Aop 一样的类,具体配置如下
<action name="token" class="com.bhr.ssh.json.action.TokenAction">
            <interceptor-ref name="defaultStack" />
            <interceptor-ref name="token" />
            <result name="invalid.token">/token.jsp</result>                        
            <result>/token.jsp</result>
        </action>

   然后在拦截器里面 获得页面上这个标签的value ; String tokenName =  getToken();
< input type ="hidden" name ="struts.token" value ="BXPNNDG6BB11ZXHPI4E106CZ5K7VNMHR" />
 然后在session里面找看是否有这个保存值,看是否session.getAttribute(tokenName);validToken();验证
一般来说第一次提交如果找到了,就把session.removeAttribute(tokenName);删除了。所以当重复提交的时候,tokenName 已经在session里面被清除了。没有保存在session里面,所以就。。。。。。。。。。。
总结:
通过Session Token :当客户端请求页面时,服务器会通过token标签生成一个随机数,并且将该随机数放到sesiion里面,然后将该随机数放到客户端,就是隐藏表单域,如果客户第一次提交,那么会将该随机数往服务器。被拦截。服务器接受到该随机数并且与session中的被保存的随机数进行对比这两者相同服务器认为是第一次提交。

 

 

分享到:
评论

相关推荐

    Struts拦截器及token拦截器防止重复提交例子源码

    Struts2拦截器的实现原理相对简单,当请求struts2的action时,Struts 2会查找配置文件,并根据其配置实例化相对的 拦截器对象,然后串成一个列表,最后一个一个地调用列表中的拦截器 三、定义Struts2拦截器。 ...

    Struts2 in action中文版

    1.3.3 Struts 2的工作原理 12 1.4 小结 14 第2章 初识Struts 2 16 2.1 声明性架构 16 2.1.1 两种配置 16 2.1.2 声明架构的两种方式 17 2.1.3 智能默认值 20 2.2 简单的HelloWorld示例 20 2.2.1 部署示例应用程序 20...

    Java中的Struts2框架拦截器之实例代码

    在看拦截器的小例子的前我们先来看看sturts2的原理   struts2自己是有拦截器的,通过拦截器可以拦截用户请求,并作出处理 拦截器作用有很多,譬如: 1.Action里面有个属性,这个属性我想在action执行之前改成别的值...

    李兴华Java Web开发实战经典(高清版) Part2

    15.4、Struts工作原理 15.5、深入Struts应用 15.6、本章摘要 15.7、开发实战讲解(基于Oracle数据库) 第16章 Struts常用标签库 16.1、Struts标签库简介 16.2、Bean标签 16.2.1、标签 16.2.2、标签 ...

    java web 视频、电子书、源码(李兴华老师出版)

    15.4、Struts工作原理 15.5、深入Struts应用 15.6、本章摘要 15.7、开发实战讲解(基于Oracle数据库) 第16章 Struts常用标签库 16.1、Struts标签库简介 16.2、Bean标签 16.2.1、标签 16.2.2、标签 ...

    李兴华 Java Web 开发实战经典_带源码_高清pdf 带书签 上

    15.4、Struts工作原理 15.5、深入Struts应用 15.6、本章摘要 15.7、开发实战讲解(基于Oracle数据库) 第16章 Struts常用标签库 16.1、Struts标签库简介 16.2、Bean标签 16.2.1、标签 16.2.2、标签 16.2.3...

    MLDN+李兴华+Java+Web开发实战经典.part3.rar )

    15.4、Struts工作原理 15.5、深入Struts应用 15.6、本章摘要 15.7、开发实战讲解(基于Oracle数据库) 第16章 Struts常用标签库 16.1、Struts标签库简介 16.2、Bean标签 16.2.1、标签 16.2.2、标签 ...

    李兴华 java_web开发实战经典 源码 完整版收集共享

    15.4、Struts工作原理 15.5、深入Struts应用 15.6、本章摘要 15.7、开发实战讲解(基于Oracle数据库) 第16章 Struts常用标签库 16.1、Struts标签库简介 16.2、Bean标签 16.2.1、标签 16.2.2、标签 16.2.3...

    李兴华 Java Web 开发实战经典_带源码_高清pdf 带书签 下

    15.4、Struts工作原理 15.5、深入Struts应用 15.6、本章摘要 15.7、开发实战讲解(基于Oracle数据库) 第16章 Struts常用标签库 16.1、Struts标签库简介 16.2、Bean标签 16.2.1、标签 16.2.2、标签 16.2.3...

    李兴华Java Web开发实战经典.pdf (高清版) Part1

    15.4、Struts工作原理 15.5、深入Struts应用 15.6、本章摘要 15.7、开发实战讲解(基于Oracle数据库) 第16章 Struts常用标签库 16.1、Struts标签库简介 16.2、Bean标签 16.2.1、标签 16.2.2、标签 ...

    李兴华 Java Web 开发实战经典 高清扫描版Part3

    15.4、Struts工作原理 15.5、深入Struts应用 15.6、本章摘要 15.7、开发实战讲解(基于Oracle数据库) 第16章 Struts常用标签库 16.1、Struts标签库简介 16.2、Bean标签 16.2.1、标签 16.2.2、标签 16.2.3...

    spring security 参考手册中文版

    37.5.2解析CsrfToken 272 第七部分 Spring数据集成 273 38. Spring Data&Spring安全配置 273 39. @Query中的安全表达式 273 第八部分 附录 274 40.安全数据库模式 274 40.1用户模式 274 40.1.1集团当局 274 40.2...

Global site tag (gtag.js) - Google Analytics