2010-09-11 98 views
1

這是一個兩部分問題。我正在構建一個閃存圖像查看器,作爲一個便攜式的年齡限制模塊(暴力視頻遊戲)。基本上,它會從CDN加載任意數量的圖像,並要求用戶在查看它之前輸入他們的生日。簡單的東西。問題是,根據公司政策,我們不能允許通過任何嗅探方式直接訪問這些圖像(例如,觀看Webkit/Firebug中的資源/網絡標籤,或者如果我們以這種方式加載它們,則觀看XHR)。所以,我希望得到您關於解決這個問題的最佳方式的意見。AS3:掩蓋加載資源

起初,我以爲有一個服務器端腳本,通過傳遞一個可以解密的動態鹽的動態加載的圖像(例如,通過PHP),例如,使用一種很不可能被發現的方法(例如,將鹽嵌入整個字符串中),但是這會破壞CDN的目的,因爲所有請求都將被定位到服務器。

然後,我認爲通過套接字加載圖像將是一個很好的解決方案,但是,我無法將二進制圖像(刪除響應頭後)轉換爲位圖。

有沒有更好的方法來解決這個問題?我知道現實中不可能完全防止內容被鏈接到(例如,某人可以截圖閃光燈),但我的目標只是採取措施防止這種情況通過本機方式發生。任何想法將不勝感激。下面是套接字代碼(不相關的部分刪除),如果有幫助的話。

package com.std.socket { 
    import flash.system.Security; 
    import flash.net.Socket; 
    import flash.events.*; 
    import flash.errors.*; 
    import flash.display.Bitmap; 
    import flash.display.MovieClip; 
    import flash.display.Loader; 
    import flash.utils.ByteArray; 

    public class SocketRequest { 
     private var root:MovieClip; 
     private var sock:Socket; 
     private var data:ByteArray = new ByteArray(); 
     private var request:Object = { 
      'host': null, 
      'port': null, 
      'uri': null, 
      'callback': null, 
      'response_parts': [] }; 

     public function SocketRequest(root:MovieClip, host:String, port:int, uri:String, callback:Function):void { 
      Security.allowDomain('*'); 
      Security.loadPolicyFile('http://foo.bar/crossdomain.xml'); 

      this.request.root = root; 
      this.request.host = host; 
      this.request.port = port; 
      this.request.uri = uri; 

      this.sock = new Socket(); 
      this.sock.addEventListener(Event.CONNECT, this.evt_socketConnect); 
      this.sock.addEventListener(Event.CLOSE, this.evt_socketClose); 
      this.sock.addEventListener(ProgressEvent.SOCKET_DATA, this.evt_socketResponse); 
      this.sock.connect(this.request.host, this.request.port); 
     } 

     private function evt_socketConnect(evt:Event):void { 
      // Send the request headers 
      this.sock.writeUTFBytes('GET ' + this.request.uri + " HTTP/1.1\n"); 
      this.sock.writeUTFBytes('Host: ' + this.request.host + ':' + this.request.port + "\n\n"); 
     } 

     private function evt_socketClose(evt:Event):void { 
      // Since this is an image, just split on header \r\n and get the last member 
      var response:Array = this.request.response_parts.join('').split("\r\n"); 
      var body:String = response[response.length - 1]; 
      var loader = new Loader(); 
      var ba:ByteArray = new ByteArray(); 
      var mc:MovieClip = new MovieClip(); 

      this.data.writeMultiByte(body, 'utf-8'); 

      loader.loadBytes(this.data); 
      mc.addChild(loader); 

      // Pass the resulting MovieClip back to the caller 
      if(typeof(this.request.callback) == 'function') 
       this.request.callback.apply(this.request.root, [mc]) 
     } 

     private function evt_socketResponse(evt:ProgressEvent):void { 
      if(!this.sock.bytesAvailable) 
       return; 
      this.request.response_parts.push(this.sock.readUTFBytes(this.sock.bytesAvailable)); 
     } 
    } 
} 

正如我在寫我在想,在SocketRequest::evt_socketResponse()this.sock.readUTFBytes()位確實應該:

this.request.response_parts.push(this.sock.readBytes(this.data, this.data.length, evt.bytesLoaded)); 

,然後從this.data去除頭,但TBH我不是超級的ByteArray -savvy。有人有想法嗎?

回答

3

有幾件事看起來與您的代碼有誤。

首先,您正在使用read/writeUTF8Bytes。這對於二進制數據不適用。您需要read/writeBytes。

其次,標題由\r\n\r\n序列終止,而不是\r\n

這是我會怎麼做:

private function evt_socketClose(evt:Event):void { 

    _buffer.position = 0; 
    var pos:int = 0; 

    while(_buffer.bytesAvailable >= 4) { 

     if(_buffer.readUnsignedByte() == 0xd && _buffer.readUnsignedByte() == 0xa 
      && _buffer.readUnsignedByte() == 0xd && _buffer.readUnsignedByte() == 0xa) { 

      var bodyBytes:ByteArray = new ByteArray(); 
      bodyBytes.writeBytes(_buffer,_buffer.position); 
      var loader:Loader = new Loader(); 
      var mc:MovieClip = new MovieClip(); 
      loader.loadBytes(bodyBytes); 
      mc.addChild(loader); 
      if(this.request.callback is Function) { 
       this.request.callback.apply(this.request.root, [mc]); 
      } 
      // this return isn't really neccesary... 
      return; 
     } 
    } 

} 

private var _buffer:ByteArray = new ByteArray(); 

private function evt_socketResponse(evt:ProgressEvent):void { 
    if(!this.sock.bytesAvailable) { 
     return; 
    } 
    var bytesToRead:uint = this.sock.bytesAvailable; 
    this.sock.readBytes(_buffer,_buffer.position,bytesToRead); 
    _buffer.position += bytesToRead; 
} 

基本上,當你接收數據,其存儲在您的緩衝區。數據完成後,您將開始讀取該緩衝區,直到找到標題的結尾(\r\n\r\n0xd,0xa,0xd,0xa)。此時,您的緩衝區位置是主體/有效負載的第一個字節。所以你從這一點讀取緩衝區到最後並將它存儲在一個ByteArray中。然後你傳遞這個ByteArray到Loader::loadBytes,如果你已經加載的是一個有效的圖像或swf,它應該被加載。

+0

很多,現在更清晰。這些修復程序完美運行。我感謝幫助! – mway 2010-09-11 20:47:17

+0

@mway。沒問題。我很高興這有幫助。 – 2010-09-12 01:08:51