在我的培训课程中我常常被问到有关保护SWF影片的问题。这里有两种方法:一种是加密代码,让它难以被别人反编译和使用;另一种方法是限制SWF文件在哪些地方可用,这样别人就不能随意将你的SWF影片放在他们的站点中。
??? 有许多商业的和免费的加密工具能够帮助你保护你的代码,其中常见的有三个ASO,SWFEncrypt,SecureSWF,我就不多讨论他们了。这里有一些方法可以借鉴用来限制SWF影片在哪些地方可以使用。
1、SWF在哪个域里面运行?
SWF文件能够检测在哪个域中运行以及是否被允许存在于这个域中。你可以写一个这样的函数:
[code]
function isDomainAllowed( allowed:Array ):Boolean
{
??? var lc:LocalConnection = new LocalConnection();
??? var domain:String = lc.domain();
??? for( var i:Number = 0; i < allowed.length; ++i )
??? {
??????? if( domain == allowed[i] )
??????? {
??????????? return true;
??????? }
??? }
??? for( var i:Number = 0; i < allowed.length; ++i )
??? {
??????? if( domain.substr( - ( allowed[i].length + 1 ) ) )
??????????????????????? == "." + allowed[i] )
??????? {
??????????? return true;
??????? }
??? }
??? return false;
}
[/code]
??? 这个函数接收一个影片允许运行域的数组做为参数,并通过这个数组检测影片是否运行在被允许的域中。如果SWF影片在其中的任何一个域或者子域中,那么函数返回true,否则返回false。
??? 你可以这样使用它:
以下内容为程序代码:
var domains:Array = new Array( ??? "bigroom.co.uk", ??? "soshow.org", ??? "localhost"????? // allow local testing ??? ); if( isDomainAllowed( domains ) ) { ??? gotoAndPlay( “content” ); // play the movie } else { ??? gotoAndPlay( “forbidden” ); // display some error message ??????????????????????????????? // - more about this later |
2、SWF运行在哪个播放器版本里面?
??? 在前面的方法中,数组中包含的本地值是允许在本地flash
开发环境或者本地WEB中测试影片的。它仍然是允许用户下载SWF并在本地运行,或者载入到其他
工程。如果你想禁止SWF的本地使用,你只需要将localhost值从允许域数组中移除。然而,如果你想严格控制本地使用一些实例(例如:仅在Flash IDE中),你需要测试影片运行在哪个版本的播放器中。可以采用如下操作:
[code]
function isPlayerAllowed( allowed:Array ):Boolean
{
??? var player:String = System.capabilities.playerType;
??? for( var i:Number = 0; i < allowed.length; ++i )
??? {
??????? if( player == allowed[i] )
??????? {
??????????? return true;
??????? }
??? }
??? return false;
}
[/code]
System.capabilities.playerType的可能值有:
ActiveX ――IE中的ActiveX 控件
PlugIn――其他浏览器中的插件
独立播放――独立播放器
外部播放――FLASH IDE中测试影片模式
isPlayerAllowed函数可以这样使用:
?
以下内容为程序代码:
var players:Array = new Array( ??? “ActiveX”, ??? “PlugIn”, ??? “External”????? // allow local testing ??? ); if( isPlayerAllowed( domains ) ) { ??? gotoAndPlay( “content” ); // play the movie }else { ??? gotoAndPlay( “forbidden” ); // display some error message } |
3、从服务器中载入文件
第三种方法就是从你的网站服务器中载入一个文件。如果载入文件失败,则忽略影片。就像这样:
?
以下内容为程序代码:
function testWithServer( callback:Function ):Void { ??? var receiver:LoadVars = new LoadVars(); ??? receiver.onLoad = callback; ??? receiver.load( “http://soshow.org/testswf.txt” ); } |
可以这样使用:
?
以下内容为程序代码:
function testResult( success:Boolean ):Void { ??? gotoAndPlay( “content” ); // play the movie } else { ??? gotoAndPlay( “forbidden” ); // display some error message } stop(); |
??? 这是非常基础的,这个文件可能是一个空的文本文件--不需要任何内容。如果文件能够被载入并且独立于载入测试文件的主机的交叉域,那么这个函数就成功了。 如果安全策略允许影片载入文件那么就成功了。这样做的优点是我们可以更改服务器上的安全策略文件来更新允许的域,而不用修改flash影片。
??? 使用一个不相关的链接是很重要的,这样能够使一部分人通过放置一些文件在服务器上来简单地避开安全设置。
还有很多方法可以增强这种方法,例如:
发送一个域信息到服务器,从服务器返回检测这个域是否被允许;
每次从flash影片加载的页面中通过获得唯一ID并通过FlashVars传递给影片,然后当询问是否被允许运行时SWF将信息反馈给服务器,服务器允许每个ID仅仅使用一次;
通过在查询及回应过程中加密(可以查看ASCrypt的一些加密代码)。
但是在大多数情况下,一个绝对URL和一个或者多个(你可以给每个SWF文件一个唯一的安全策略文件,它可以通过System.security.loadPolicyFile()加载进来)交叉域策略文件也就足够了。
总结:
这三种方法可以单独使用,也可以一起使用。一般来说,我喜欢在flash影片中使用前两个,而不从服务器获取内容。相对应的,最后一
种方法可以让你不用编辑flash影片也能更新被允许的域,这样也有它的优点。注意,如果你的源代码能够被反编译,那么这些测试都能够一起被简单的移除
掉,所以你需要结合其他的加密算法。
如果不允许回放怎么办?
如果你的影片不允许播放怎么办?有两个基本方法你可以借助:
告诉用户发生了什么事情--显示一条信息,像这样:“这个影片/游戏/其他可以在http://soshow.org/funkyswf.html
观看到”。
因此播放器需要一点缓冲的时间,创建一个初始循环来完成这个。
我根据个别情况来选择使用这些方法。
第二种方法给潜在的盗用者极少的线索去了解发生了什么,但是你还是要用第一种方法来告诉用户到哪里去合理的或者SWF影片(包括价格多少)。
我希望这些能对你有用。你采用哪种安全技术呢?
另外一种方法是通过数据库,利用数据库来存储多个常量,这些常量可以在运行的时候载入并在应用程序中使用。
如果这个结合你提到的工具使用,那么这些都是非常困难的,首先判断发生了什么,其次成功的获取每个变量的无效值并重新发送来代替数据库的功能。事实上,更多的努力是值得的!