[이 글은 이전에 쓰던 블로그에서 작성된 이후 새 블로그로 이전된 글입니다.]

사실 코드만 공개해도 되지만, 플래시의 보안 정책에 대한 이해 없이 코드만 본다면 아무런 도움이 안 될 것 같아서 설명하다 보니 조금 길어졌네요

다큐멘트 클래스처럼 적용시킵니다. AIR 설정에서 ‘포함된 파일’ 부분에 ‘policy.xml’ 이름을 가진 정책 파일 형태의 파일을 넣어주세요.

MIT 라이센스하에 배포하구요, 이것만 가지고는 소켓 서버를 못 만듭니다. 그냥 정책 파일 보내는 예제입니다.

정책 파일 보내는 포트와 실제 연결 포트가 다르다고 가정하고 짠 소스입니다.

클라이언트 측에서는 Security.loadPolicyFile("xmlsocket://127.0.0.1:843"); 등의 형태로 정책 파일을 요청하면 됩니다.

package {
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.events.ProgressEvent
    import flash.events.ServerSocketConnectEvent;
    import flash.filesystem.File;
    import flash.filesystem.FileMode;
    import flash.filesystem.FileStream;
    import flash.net.ServerSocket;
    import flash.net.Socket;

    import fl.controls.TextArea;

    public class MySocketServer extends Sprite {
        private const TARGET_IP:String = "127.0.0.1"; //타겟 IP

        private var policyServer:ServerSocket;
        private const POLICY_PORT:int = 843; //타겟 포트

        public function MySocketServer():void {
            policyServer.addEventListener(ServerSocketConnectEvent.CONNECT, onPolicyConnected);
            policyServer.addEventListener(Event.CLOSE, serverClosed);

            policyServer.bind(POLICY_PORT, TARGET_IP); //서버 소켓을 바인드시킵니다.
            policyServer.listen();
        }

        private function onPolicyConnected(e:ServerSocketConnectEvent):void {
            var tmpSocket:Socket = e.socket as Socket;

            tmpSocket.addEventListener(ProgressEvent.SOCKET_DATA, policyDataHandler); //소켓의 정책 파일 요청을 감지합니다.
            tmpSocket.addEventListener(Event.CLOSE, onPolicyClosed);
            tmpSocket.addEventListener(IOErrorEvent.IO_ERROR, IOErrorOccured);
        }

        private function policyDataHandler(e:ProgressEvent):void {
            var tmpSocket:Socket = e.target as Socket;

            var message:String = tmpSocket.readUTFBytes(tmpSocket.bytesAvailable);

            sendPolicyFileTo(tmpSocket);
        }

        private function onPolicyClosed(e:Event):void {
            var tmpSocket:Socket = e.target as Socket;

            tmpSocket.removeEventListener(ProgressEvent.SOCKET_DATA, policyDataHandler);
            tmpSocket.removeEventListener(Event.CLOSE, onPolicyClosed);
            tmpSocket.removeEventListener(IOErrorEvent.IO_ERROR, IOErrorOccured);
        }

        private function IOErrorOccured(event:IOErrorEvent):void {
            trace("IOError : " + event.text);
        }

        private function sendPolicyFileTo(target:Socket):void {
            //AIR FLA 안에 정책 파일의 형태로 policy.xml을 넣어주세요.
            //AIR2 설정의 포함된 파일 부분에 넣으시면 됩니다.

            var file:File = new File(File.applicationDirectory.nativePath + File.separator + "policy.xml");
            var stream:FileStream = new FileStream();
            stream.open(file, FileMode.READ);
            var data:String = stream.readUTFBytes(stream.bytesAvailable);

            target.writeUTFBytes(data);
            target.writeByte(0);
            target.flush(); //소켓에 정책 파일을 보냅니다.
        }
    }
}

[이 글은 이전에 쓰던 블로그에서 작성된 이후 새 블로그로 이전된 글입니다.]

정책 파일은 서버 내에 여러 개 위치할 수 있습니다. 플래시 플레이어에서 연결을 요청하면 기본적으로 루트 도메인의 /crossdomain.xml이라는 URL 정책 파일과 포트 843에서 소켓 정책 파일을 찾습니다.

정책 파일 중 이러한 정책 파일들을 ‘마스터 정책 파일’이라고 합니다.

소켓 연결의 경우 소켓 연결 위치와 같은 포트에서도 정책 파일을 찾지만, 이러한 정책 파일은 ‘마스터 정책 파일’로 간주되지 않습니다.

마스터 정책 파일은 일반적인 액세스 지정 외에도 메타 정책 문이 포함될 수 있습니다. 이 ‘메타 정책 문’에서 서버 내의 정책 파일들의 권한을 지정할 수 있습니다.

URL 정책 파일

URL 정책 파일에 대한 기본 메타 정책은 master-only이므로, 마스터 정책 파일 이외의 다른 정책 파일들은 무시됩니다.

플래시 플레이어 9 까지 URL 정책 파일에 대한 기본 메타 정책은 all이었으나,
사용자가 서버에 crossdomain.xml을 업로드 -> 그 crossdomain.xml을 정책 파일로 사용 -> 서버 데이터 접근
과 같은 방식으로 악용될 수 있어 플래시 플레이어 10에서 바뀌게 되었습니다.

보다 자세한 사항은 링크를 참조하세요.

swf 파일에서 Security.loadPolicyFile()을 이용해 다른 정책파일이나 다른 디렉터리 위치를 참조할 수 있습니다. 그러나 마스터 정책 파일에서 허용된 파일이 아니라면 이 요청은 무시됩니다.

(myserver.com/flash/crossdomain.xml을 로드 요청 하더라도 myserver.com/crossdomain.xml에서 메타 정책이 허용되어 있어야 함)

마스터 정책 파일을 확인할 때 플래시 플레이어는 3초간 서버 응답을 기다리고, 서버 응답이 없다면 마스터 정책 파일이 없다고 간주합니다.

그러나 loadPolicyFile()를 사용할 경우 플래시 플레이어는 호출되는 파일이 있다고 가정하고 파일을 로드하는데 필요한 시간동안 기다립니다. 따라서 loadPolicyFile()를 사용하여 명시적으로 파일을 호출하는 방법을 권장합니다.

소켓 정책 파일

플래시 플레이어는 연결을 요청하면 포트 843에서 제공되는 소켓 정책 파일을 찾습니다. URL 정책 파일과 마찬가지로 이것을 마스터 정책 파일이라 합니다.

URL 정책 파일과 마찬가지로 소켓 정책 파일은 정책 파일을 제공할 수 있는 포트를 지정할 수 있는 메타 정책 문을 지원합니다. 하지만 소켓 정책 파일의 기본 메타 정책은 all이므로, 마스터 정책 파일에서 제한을 두지 않는 한 모든 포트에서 정책 파일 로드가 가능합니다.

플래시 플레이어는 연결 요청 시 포트 843과 연결이 요청된 포트에서 소켓 정책 파일을 찾습니다. 다른 포트에서 정책 파일을 찾으려면 다음과 같이 loadPolidyFile()을 이용해 포트를 지정해 주어야 합니다.

Security.loadPolicyFile("xmlsocket://myserver.com:2525");

소켓 서버를 구현하고 소켓 정책 파일을 제공해야 할 필요가 있는 경우 연결되는 소켓과 같은 포트에서 정책 파일을 제공할 지 아니면 다른 포트에서 제공할 지를 결정해야 합니다. 두 경우 모두 서버에서 소켓 정책 파일을 보내기 전 클라이언트의 요청을 기다려야 합니다.

플래시 플레이어에서 연결을 요청할 때는 항상 연결이 설정된 직후 다음 문자열을 전송합니다.
<policy-file-request/>

플래시 플레이어의 요청은 null 바이트로 종료되며, 서버의 응답도 null 바이트로 종료되어야 합니다.

참조

링크 1
링크 2

[이 글은 이전에 쓰던 블로그에서 작성된 이후 새 블로그로 이전된 글입니다.]

플래시 보안 정책 파일은 웹 서버의 데이터를 다른 곳에서 사용할 수 있도록 하기 위해 사용자가 서버에 작성하는 파일입니다.

보안 정책 파일은 다음을 포함한 많은 에셋에 영향을 줄 수 있습니다.
– 비트맵, 사운드 및 비디오 데이터
– XML 및 텍스트 파일 로드
– 다른 서버에 올려져 있는 SWF 파일을 로드하는 SWF 파일
– 소켓 및 XML 소켓 연결에 대한 액세스

Flash Player는 정책 파일 로드에 두 종류의 서버 연결 방식을 지원합니다.
– URLLoader 클래스 등을 이용한 통신은 URL 기반의 로드 방식(crossdomain.xml)을 사용합니다.
– Socket 및 XMLSocket 클래스를 사용할 때는 하위 TCP 수준에서 직접 소켓 정책 파일을 가져옵니다.

추가로, 정책 파일을 가져올 때 사용하는 방법은 연결할 때 사용하는 방법과 같아야 합니다. URL 방식으로 보안 정책 파일을 가져오더라도 소켓 방식으로 같은 서버에 연결할 수 없습니다.

플래시에서 연결을 요청하면 자동적으로 정책 파일 로드를 시도합니다. 이 때, 서버의 루트 디렉토리의 /crossdomain.xml이라는 URL 기반 정책 파일을 찾고, 포트 843에서 소켓 정책 파일 로드를 시도합니다. 요청한 연결은 대기열에 저장되어 정책 파일 로드 완료 후 실행됩니다.

참조

어도비 레퍼런스

[이 글은 이전에 쓰던 블로그에서 작성된 이후 새 블로그로 이전된 글입니다.]

우선 소켓서버와 소켓간의 연동도 외부와의 통신이기 때문에 보안 샌드박스에 대한 이해가 필요합니다.

플래시의 보안 샌드박스는 네 가지로 나뉘는데,

1. local-with-filesystem

특별한 설정을 하지 않으면 자동으로 이 샌드박스가 선택됩니다. 이 샌드박스에서 플래시 플레이어는 URLLoader 등으로 로컬 파일을 읽을 수는 있지만, 서버와의 통신은 불가능합니다.

사용자는 자신의 로컬 정보가 네트워크를 통해 누출되지 않음을 확신할 수 있습니다.

2. local-with-networking

로컬 파일에서 네트워크 연동을 할 때 사용되는 샌드박스입니다.

이 샌드박스에서 플래시 플레이어는 서버와 데이터를 주고 받을 수 있으나, 로컬파일에는 액세스가 불가능합니다.

그러나 서버측에서 크로스도메인 관련 파일이나, Security.allowAccess 메서드를 이용해 swf 파일을 허용해 주어야 합니다.

3. local-trusted

신뢰할 수 있는 파일로 등록된 swf 파일입니다.

local-trusted 샌드박스의 swf 파일은 다른 swf 파일과 상호작용하고 로컬과 서버 모두에 접근할 수 있습니다.

4. remote

인터넷 상에 embed 등의 형식으로 붙여 넣어진 플래시 파일입니다.

이 샌드박스에서는 로컬 파일에 액세스 할 수 없으며, 같은 서버의 리소스에는 접근이 허용되지만 외부 서버의 접근에는 local-with-networking 샌드박스와 같이 크로스도메인 파일이나 Security.allowAccess가 필요합니다.

플래시에서 샌드박스 타입 설정은 ‘파일-제작 설정’에서 가능하며 로컬 파일만 액세스와 네트워크만 액세스를 선택할 수 있습니다.

웹 상에 올린 플래시는 모두 remote 샌드박스 안에서 작동하구요, exe 파일이나 테스트 플레이로 실행한 파일들은 local-trusted 샌드박스 안에서 작동합니다.

참조

어도비 레퍼런스