首先我們看一下以下這篇文章:
http://www.adobe.com/devnet/flashplayer/articles/socket_policy_files.html
注意以下內容:
Socket policy request process
Flash Player checks for a socket policy file in three places for each IP connection. The checks occur in the following order:
- Flash Player first checks port 843 to determine if there is a socket master policy file. If there is no socket master policy file or the socket master policy file has a
site-control
tag specifying"all"
, then Flash Player proceeds to the next step. If thesite-control
tag has a value of"none"
, then the process stops and the socket is denied a connection. - If an ActionScript
Security.loadPolicyFile()
command exists within the SWF file, then the Flash Player runtime checks that location. Flash Player checks the destination of theloadPolicyFile()
only after it has checked the master policy file on port 843 for permission to acknowledge other policy files. If the developer has not specified aloadPolicyFile()
command, then Flash Player checks the destination port of the connection. - The destination port of the connection is the last check made by Flash Player. This check is only performed if the socket master policy file permits Flash Player to check additional locations. If Flash Player still cannot locate a policy file granting permission, then the socket connection is denied.
What data is sent in the request and response?
The request for a policy file is very simple: Flash Player sends the string <policy-file-request/>
followed by aNULL
byte to the port where it is requesting a policy file; no more, no less. Flash developers cannot modify the string that is sent. In return, Flash Player expects to receive the socket policy file as text. Once Flash Player receives the socket policy file, it closes the connection and opens a new connection if the policy file approves the request.
Security.loadPolicyFile("xmlsocket://yourpolicyserver:port");
然後在指定端口監聽,並返回策略文件即可
如下(使用apache mina):
package com.the4thcity.chat.flash;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import org.apache.log4j.Logger;
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.LineDelimiter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.filter.ssl.SslFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import com.the4thcity.chat.ChatConstant;
import com.the4thcity.chat.ssl.BogusSslContextFactory;
public class PolicyServer implements Runnable {
private static final Logger log = Logger.getLogger(PolicyServer.class);
private String hostname = "localhost";
private int port = 843;
private boolean useSSL = false;
private NioSocketAcceptor acceptor;
public PolicyServer(String hostname, int port, boolean useSSL) {
super();
this.hostname = hostname;
this.port = port;
this.useSSL = useSSL;
init();
}
private void init() {
try {
acceptor = new NioSocketAcceptor();
DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();
// addLogger(chain);
// MdcInjectionFilter mdcInjectionFilter = new MdcInjectionFilter();
// chain.addLast("mdc", mdcInjectionFilter);
if (useSSL) {
addSSLSupport(chain);
}
acceptor.getFilterChain().addLast(
"codec",
new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName(ChatConstant.CODEC_CHATSET),
LineDelimiter.NUL, LineDelimiter.NUL)));
acceptor.setHandler(new PolicyIoHandler());
} catch (Exception e) {
log.info("[chat Policy error] ", e);
}
}
private void addSSLSupport(DefaultIoFilterChainBuilder chain) throws Exception {
SslFilter sslFilter = new SslFilter(BogusSslContextFactory.getInstance(true));
chain.addLast("sslFilter", sslFilter);
log.info("[chat Policy] SSL ON");
}
private void addLogger(DefaultIoFilterChainBuilder chain) throws Exception {
chain.addLast("logger", new LoggingFilter());
log.info("[chat Policy] Logging ON");
}
@Override
public void run() {
try {
acceptor.bind(new InetSocketAddress(hostname, port));
log.info("[chat Policy] started server, linsten[" + hostname + "] on port:" + port);
} catch (IOException e) {
log.info("[chat Policy eror]:", e);
}
}
}
PolicyIoHandler.java
package com.the4thcity.chat.flash;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import org.apache.log4j.Logger;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import com.the4thcity.chat.ChatConstant;
public class PolicyIoHandler extends IoHandlerAdapter {
private static final Logger log = Logger.getLogger(PolicyIoHandler.class);
@Override
public void exceptionCaught(IoSession session, Throwable cause) {
cause.printStackTrace();
log.warn("Unexpected exception.", cause);
session.close(true);
}
@Override
public void messageReceived(IoSession session, Object ioMessage) {
String message = (String) ioMessage;
if (ChatConstant.FLASH_SECURITY_REQUEST.equals(message)) {//策略文件
String value = "<?xml version=\"1.0\"?>" + "<cross-domain-policy>"
+ "<allow-access-from domain=\"*\" to-ports=\"*\" />" + "</cross-domain-policy>\0";
log.info("return Policy :" + value);
IoBuffer ioBuffer = IoBuffer.allocate(value.getBytes().length);
ioBuffer.setAutoExpand(true);
if (value != null) {
try {
ioBuffer.putString(value, Charset.forName(ChatConstant.CODEC_CHATSET).newEncoder());
} catch (CharacterCodingException e) {
e.printStackTrace();
}
}
ioBuffer.flip();
session.write(ioBuffer);
}
}
@Override
public void sessionOpened(IoSession session) throws Exception {
super.sessionOpened(session);
}
@Override
public void sessionClosed(IoSession session) throws Exception {
super.sessionClosed(session);
}
}
ChatConstant.java
public class ChatConstant {
public static final String FLASH_SECURITY_REQUEST = "<policy-file-request/>";
public static final String CODEC_CHATSET = "UTF-8";
}