AS3: скрытие загруженных ресурсов - PullRequest
1 голос
/ 11 сентября 2010

Это своего рода вопрос из двух частей. Я создаю флеш-просмотрщик изображений, чтобы он был портативным модулем с ограничением по возрасту (жестокие видеоигры). В основном, он будет загружать любое количество изображений из CDN и потребовать от пользователя указать свой день рождения перед его просмотром. Простые вещи Проблема заключается в том, что в соответствии с политикой компании мы не можем допустить, чтобы эти изображения были доступны напрямую с помощью любого сниффинга (например, просмотра вкладки «Ресурсы / Сеть» в Webkit / Firebug или просмотра XHR, если мы загрузили их таким образом). Итак, я хотел бы узнать ваше мнение о том, как лучше к этому подойти.

Сначала я подумал, что у меня есть серверный скрипт, который загружает изображение (например, через 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, но я не супер-подкованный ByteArray. У кого-нибудь есть мысли?

1 Ответ

3 голосов
/ 11 сентября 2010

Пара вещей выглядит неправильно с вашим кодом.

Во-первых, вы используете read / writeUTF8Bytes. Это не будет работать правильно для двоичных данных. Вам нужно читать / писатьBytes вместо этого.

Во-вторых, заголовок завершается последовательностью \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\n или 0xd,0xa,0xd,0xa). В этот момент ваша позиция в буфере является первым байтом тела / полезной нагрузки. Таким образом, вы читаете буфер от этой точки до конца и сохраняете его в ByteArray. Затем вы передаете этот ByteArray в Loader::loadBytes, и если то, что вы загрузили, является допустимым изображением или SWF, оно должно быть загружено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...