您的位置:首页 > 其它

flash socket通讯安全沙箱问题解决(附带案例)

2013-11-01 15:55 387 查看

一、flash socket通讯安全沙箱问题解决

flash发起socket通讯的三个过程:

1、当封装在页面的flash发起socket通讯请求的时候会寻找服务器端843端口, 获取crossdomain.xml文件。

2、当服务器没有开启843的时候,flash player会检查发起请求的swf文件中有没有使用Security.loadPolicyFile(xmlsocket://127.0.0.1:4299)

来加载策略文件crossdomain.xml。

3、如果没有就会看这个发起请求的swf要连接的目标端口有没有策略文件。

如果上述三个步骤都没有找到策略文件,那么出现连接失败并出现错误提示:

[SecurityErrorEvent type="securityError" bubbles=false cancelable=false eventPhase=2 text="Error #2048"]

二、 产生该问题的原因:

新版的flash player,当flash文件要进行socket通讯的时候,需要向服务器端 获取crossdomain.xml文件,如果找不到就会出现上述问题。

(老版的flash player无论你采用的是http请求方式或者xmlsocket socket方式, 他们都共用一个安全策略文件,这个策略文件只要你放在主域的目录下就行,

而新版的要求,如果你使用http请求方式需要把策略文件放在目录下面,如果你使用的socket请求方式就必须通过socket端口来接收这个策略文件。

其对应的调用的方式为:

http请求:Security.loadPolicyFile("http://www.xxx.com/crossdomain.xml");

socket或xmlsocket请求:Security.loadPolicyFile("xmlsocket://www.xxx.com:port");)

三、那么怎么将socket策略文件发送给flash player。

三种方法:

一、使用默认843端口

flash player在你的socket.connect(address,port);运行之前,会按照三个过程向你的socket 服务器的843端口发送一个字符串 "<policy-file-request/>" ,

这个时候如果你有一个服务器在监听843端口那么受到这个字符串之后,直接按照xml格式发挥策略文件就解决了。

二、使用自定义端口(推荐使用)

当然你也可以自己设置一个端口,不过这个时候不能用Http方式,而要用xmlsocket方式。相当于自动帮你新建一个xmlsocket对象,

然后连接你指定的主机和端口, 比如你想用1234端口可以在你的flash里面加这一句Security.loadPolicyFile("xmlsocket://www.xxx.com:1234")

需要注意的是这一句要加在你的socket.connect()前面。

三、代码发送策略文件。

在你的socket连接端口监听这个请求,比如你用的是socekt.connect("127.0.0.1",3333);

那么在你的服务器加一段接受字符串"<policy-file-request/>"的代码,当接收到这个字符串 的时候将策略文件按照xml格式发到客户端。

四、如何配置安全策略文件

1、针对web应用的策略文件

示列为策略文件允许访问源自:*game.com和192.168.1.1的swf文件

<?xml version = "1.0" encoding = "utf-8"?>

<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">

<cross-domain-policy>

<allow-access-from domain="*.game.com" />

<allow-access-from domain="192.168.1.1" />

</cross-domain-policy>

注意事项:

默认情况下,策略文件必须命名为 crossdomain.xml,并且必须位于服务器的根目录中。但是,SWF 文件可以通过调用

Security.loadPolicyFile() 方法检查是否为其它名称或位于 其它目录中。跨域策略文件仅适用于从其中加载该文件的目录

及其子目录。因此,根目录中的策略文件适用于整个服务器, 但是从任意子目录加载的策略文件仅适用于该目录及其子目录。

2、针对socket的策略文件

<?xml version = "1.0" encoding = "utf-8"?>

<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">

<cross-domain-policy>

<allow-access-from domain="*" to-ports="507" />

<allow-access-from domain="*.example.com" to-ports="507,516" />

<allow-access-from domain="*.example2.com" to-ports="516-523" />

<allow-access-from domain="www.example3.com" to-ports="*" />

</cross-domain-policy>

这个策略文件是指定允许哪些域的主机通过哪些端口链接。

五、示例代码

java socket服务端:

安全策略服务器:
public class SecurityServer
{
private int count = 0;
public  String xml = "";
private InputStream is;
private OutputStream os;

public void start() throws Exception
{
xml += "<cross-domain-policy>";
xml += "<allow-access-from domain=\"*\" to-ports=\"*\" />";
xml += "</cross-domain-policy>";

ServerSocket serverSocket = new ServerSocket(4299);
System.out.println("等待用户连接``并发送策略文件``````");
while (true)
{
try
{
Socket socket = serverSocket.accept();
count++;
this.is = socket.getInputStream();
this.os = socket.getOutputStream();
byte[] temp = new byte[300];
this.is.read(temp);
this.os.write(this.xml.getBytes("utf-8"));
this.os.flush();
this.os.close();
this.is.close();
socket.close();
} catch (Exception e)
{
System.out.println("服务器发生异常");
}
}
}
public static void main(String[] args)
{
try
{
new SecurityServer().start();
} catch (Exception e)
{
System.out.println("Socket发生异常:" + e);
}
}
}


主连接服务器:
public class ServerJava
{
private int count =0;

public void start() throws Exception
{
ServerSocket serverSocket = new ServerSocket(4399);
System.out.println("等待用户连接````````");
while (true)
{
try
{
Socket socket = serverSocket.accept();

count++;
System.out.println("连接成功``数量: `````"+count);

ServerThread thread = new ServerThread(socket);
thread.start();
} catch (Exception e)
{
System.out.println("服务器发生异常");
}
}
}
public static void main(String[] args)
{
try
{
new ServerJava().start();
} catch (Exception e)
{
System.out.println("Socket发生异常:" + e);
}
}
}


服务端读取客户端数据:
public class ServerThread extends Thread
{
private Socket socket;
private BufferedReader input;
private PrintWriter output;
private OutputStream os;
private InputStream is;

public ServerThread(Socket socket)
{
this.socket = socket;
}
public void run()
{
System.out.println("---------------启动一个线程-----------------");
try
{
this.os = this.socket.getOutputStream();
this.is = this.socket.getInputStream();
byte[] temp = new byte[1000];
int len = 0;
StringBuffer msg = new StringBuffer();

while ((len = this.is.read(temp)) > 0)
{
msg.append(new String(temp, 0, len,"UTF-8"));
if(len<1000){
this.os.write(msg.toString().getBytes("UTF-8"));
this.os.flush();
msg = new StringBuffer();
}
}
} catch (Exception e)
{
System.out.println("子线程发生异常");
try
{
input.close();
output.close();
} catch (Exception ex)
{
System.out.println("关闭资源发生异常");
}
System.out.println("子线程结束了");
}
}
}


as3客户单端代码:

package {
import flash.net.Socket;
import flash.events.ProgressEvent;
import flash.events.Event;
import flash.utils.ByteArray;
import flash.display.Sprite;
import flash.system.Security;
import flash.text.TextField;
import flash.events.MouseEvent;
public class ClientSocket extends Sprite {
private var count:uint=0;
private var clientSocket:Socket;
private var readBytes:ByteArray = new ByteArray();
private var writeBytes:ByteArray = new ByteArray();
public function ClientSocket() {
conn.addEventListener(MouseEvent.CLICK,connServer);
send.addEventListener(MouseEvent.CLICK,sendToServer);
}

private function connServer(evt:MouseEvent):void {
clientSocket = new Socket();
Security.allowDomain("*");
Security.loadPolicyFile("xmlsocket://127.0.0.1:4299")
clientSocket.connect("127.0.0.1",4399);
clientSocket.addEventListener(Event.CONNECT,successConn);
clientSocket.addEventListener(ProgressEvent.SOCKET_DATA,reviceData);
}

private function successConn(evt:Event):void {
count++;
dyText.text="连接成功"+count+"\n";
}
private function sendToServer(evt:Event):void {
var charContext=inputText.text;
dyText.text=dyText.text+charContext+"\n";
//utf-8转码
clientSocket.writeUTFBytes(charContext);
clientSocket.flush();
}

private function reviceData(evt:Event):void {

trace(totalLen+"======revice message===============");
var totalLen:uint=clientSocket.bytesAvailable;
server.text=clientSocket.readUTFBytes(totalLen);
}
}
}


将swf文件发布到网页上进行测试
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: