CSK.Blog--个人原创Weblog

« 疲劳和安慰该死的网易和见鬼的松闵线 »

用令牌信息来验证Flash提交信息的合法性

今天GRE学好回来的比较早,那就说一下昨天提到的问题: 首先我把事情交待清楚,也许你正需要解决这个的方法^_^ 搞过动态网页脚本比如ASP的朋友都知道,有一个HTTP_REFER的系统变量可以获得本次请求是又那个页面提交的。

换句话说,可以用这个东西来知道用户是通过那个页面或其他网站上页面的连入本网站的。

用这个可以进行防盗链检测。

比如www.websiteA.com上有一个文档:aaa.asp。websiteA不希望其他网站盗链到这个页面。于是他就在aaa.asp做了些检测,比如:

  if Instr(1,LCase(request.ServerVariables("HTTP_REFER")),"http://www.websitea.com") <>1 Then
     response.write "对不起,您是通过其他网页的盗链进入该网页的"
     response.End
  End IF

上面的意思就是说,首先获取用户是通过哪个页面进入该文档的,比如用户在www.websiteB.com/bbb.asp上的一个超链接连入了aaa.asp。那么request.ServerVariables("HTTP_REFER")就返回值www.websiteB.com/bbb.asp

于是知道,在"www.websiteB.com/bbb.asp"中是找不到子串"http://www.websitea.com"的,于是就可以判定该页面被盗链了,于是拒绝显示信息。

 当然HTTP_REFER还能用来做页面访问统计,还有在高手挑战2中就是用它来做关卡跟踪的,但这和本主题无关,所以想知道详情就自己找吧。 接下来就进入正题了。

那Flash和HTTP_REFER有什么关系呢?

这里就不是单纯的盗链问题。我认为一般下面几种情况是需要判断HTTP_REFER的。 比如我在网站上写了一个Flash游戏,游戏结束后允许玩家上传自己的姓名和得分。

这就会出现安全问题:做过Flash交互的人都知道,Flash和后台网页脚本的交互手段目前一般是用MovieClip.LoadVarible();和XML.sendAndLoad()方法。这没什么问题,但服务器是不会判断提交数据的真实性的,只要我协议和语法格式一致,任何人在任何地方都能提交一个伪造的“得分”到服务器。而如果那个游戏时对高分进行奖励的,那损失可不小。

那么是不是也能用HTTP_REFER来解决呢?理论上似乎可以,但试过人会发现,那该死的FlashPlayer是不会发送Refer数据的(可能为了安全性)。这样HTTP_REFER就完全失效了。 也有人想出来用密码首先加密数据,这个的确是办法,但就要看怎么实现了。如果这个游戏本来就是需要采用帐号登陆后进行的,那么密码是由玩家提供,问题也能解决。但如果没有登陆这一关,似乎密码就只能保存在swf文件中了。 但现在Flash完全是透明的东西。外面各种反编译软件可以很轻松的把swf高保真的还原到fla格式。这个密码也自然形同虚设……而且上面的登陆办法也有问题:如果玩家本人提交伪造数据呢? 最近设计ReformPost时候我也考虑到这个问题。

其实解决办法也不是什么新鲜的,就是采用目前比较常见的防治伪造数据包的办法,在提交表中附上令牌(Token) 说白了,令牌就是一个密钥。他首先由服务器给出,今后在客户端和服务器间的通讯都是需要密钥验证,如果发来的信息的密钥不存在或与当前的不符,则认为是伪造数据。 对于上面的大家都懂。那么怎么用Token来保护Flash通讯?关键就是在服务端何时在何地,用何种方式“告诉”Flash了我采用的办法是:首先在flash所在的页面中给出Token(需要动态脚本页)。比如服务端自动产生如下JavaScript插入在Flash所在的页面里

function GetToken()
{
   swfOcx.OnGetToken(strToken);
}

其中strToken是服务器每次产生的不重复序列(可以用当前时间),swfOcx是插入Flash的元素对象。 呵呵,想起来了吗?Flash8开始有了个新特性,可以利用ExternalInterface类随意访问外部JavaScript函数,也可以从外部JavaScript调用Flash中的用户函数。 下面就给出Flash中主动获得服务端给出的Token的代码:

import flash.external.*;
var strTokenID:String;

function OnGetToken(strToken:String) {
  strTokenID = strToken;
  play();
}
ExternalInterface.addCallback("OnGetToken", null, OnGetToken);
ExternalInterface.call("GetToken");

首先调用外面的GetToken函数,然后GetToken调用了flash中注册的OnGetToken,并把Token作为参数传递回来。 p.s.其实应该可以直接用ExternalInterface.call一次性调用,利用函数返回值取得Token,但我试了几次都失败了,所以就采用这个折中的办法。 至于以后的事情我就不多说了。这样我们的目的也就达到了。呵呵,其实这都怪Adobe不好……(以前要怪macromedia) 恩,然后我再写篇别的...

 

  • quote 1.gxk
  • 请问应该怎么用呢
    我的FLASH页面在show.asp.我在这个页面加 了function GetToken()
    {
    swfOcx.OnGetToken(strToken);
    }
    然后在FLASH也加了代码,在不知道怎么用,或者说怎么判断,在什么时候判断?
  • 5/3/2006 12:53:15 PM 回复该留言
  • quote 3.heaven
  • 呵呵,看来你没理解他的作用。客户端是能看到,但别人就没法盗用了阿
  • 5/4/2006 5:38:54 PM 回复该留言
  • quote 4.gxk
  • 既然客户端能看到,那这个令牌信息就可以伪造啊

    我自己做一个FLASH,提交的时候把令牌信息写上就可以了啊

    heaven能告诉我怎么用吗,是不是我用的方法不对
    我是在FLASH里提交令牌信息,然后在FLASH在的ASP页面与原来的令牌比较
  • 5/4/2006 8:22:28 PM 回复该留言
  • quote 5.heaven
  • http://www.csksoft.net
  • 呵呵,这个令牌别人看到是无关的,因为我的目的是不让别人在其他网页中调用它,即使他在其他页面(非我的网站)使用了看到的令牌,这绝对不可能会和我网站中记录的令牌一致(你自己想想是为何吧)。这样目的也就达到了
  • 5/4/2006 9:10:04 PM 回复该留言
  • quote 6.gxk
  • heaven我试过,我从本地的FLASH提交到远程的网站,我用同样的令牌信息,提交到远程页面,结果可以成功写入远程网站数据库.
    我的是时间做为令牌,麻烦您看一下这样对吗
    <script language=javascript>

    function GetToken()
    {
    swfOcx.OnGetToken(2006-5-4 22:07:44);
    }

    </script>这个时间是取的服务器的时间,在网页点右键查看源代码,就是这样子了
  • 5/4/2006 10:11:25 PM 回复该留言
  • quote 7.gxk
  • 在FLASH中我是把strTokenID这个值,提交到FLASH在的页面,然后和服务器的令牌做比较的

    但是我发现别人知道了这个令牌值,是可以自己提交的,我就试过,本地的FLASH可以提交到远程数据库的
  • 5/4/2006 10:20:42 PM 回复该留言
  • quote 8.HEAVEN
  • 这样吧,你用e-mail或qq与我联系吧。我和你说下
  • 5/5/2006 7:39:35 AM 回复该留言

发表评论:

注意:为了有效防止SPAM,任何含有http://字样的消息会被阻止发布同时,本站仅供技术交流,请不要讨论任何政治敏感话题或者低级趣味问题。

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

日历

最新评论及回复

最近发表

Copyright Shikai Chen 2000-2012. Powered By Z-Blog(CSK Modified)