Securing Flash Media Interactive Edition

A critical component to rich media is securing your content and resources. In this article I am going to cover how to restrict someone with the Flash Media Live Encoder or for that matter any encoder from publishing to the Flash Media Interactive Server. In the process I am going to show you how to allow someone with the appropriate permissions and the Flash Media Live Encoder to publish to the server.

There are many ways to accomplish this goal. First there are Adobe partners that have written plugins for the Flash Media Server that allow you to restrict access to the server through the use of these plugins.

There are also server side APIs that allow you to connect with other systems and data. For instance you can use the WebService class to create and access a WSDL/SOAP web service or the XML class lets you load, parse, send, build, and manipulate XML.

In this short example I am going to use a server side event “onPublish” to retrieve the querystring and respond to a request to publish a live stream from the Flash Media Live Encoder to the Flash Media Interactive Server. Now there is a reason that I am calling out the Flash Media Interactive Edition and not the Streaming Edition and that is that the Streaming Edition does not support server side scripting.

Server side scripts are written and stored in “.asc” files in an application directory inside the application folder on your Flash Media Server. As an example if I had a application called foo I would store my server side script (e.g. main.asc)  in the following location.

server side script location

There are a number of events that you can work with on the server side; for instance onAppStart, onConnect, onPublish. You can find information about these and other events, methods and properties in the documentation.

Lets take a look at the final server side script in the main.asc file.

application.onAppStart=function(){
trace(“***** on App Start”);
}

application.onConnect=function(clientObj){
trace(“**** on connect”);
this.acceptConnection(clientObj);
return true;
}

application.onPublish = function(clientObj, streamObj){
logon = extractQueryString(streamObj.publishQueryString, “logon“);
if(logon != “fmle”){
application.disconnect(clientObj);
trace(“Sorry you aint publishing”);
}

}
function extractQueryString(queryString, arg){
var returnValue = “”;
temp = arg + “=”;
i = queryString.indexOf(temp);
if (i != 0){
temp = “&” + arg + “=”;
i = queryString.indexOf(temp);
}
if (i != -1){
returnValue = queryString.substr(i+temp.length);
i = returnValue.indexOf(“&”);
returnValue = returnValue.substr(0, i);
}
return returnValue;
}

In the preceding code the events are in bold. The helper function that will extract the search term (i.e. the second parameter that we pass in to the extractQueryString function called arg)  that we tell it from the querystring is green. The bit that disconnects an in appropriate publisher is red.

First let me say that this is a very simple example that should be coupled with functionality that does more to integrate with existing systems (e.g. ldap) but after many calls from customers concerned that someone might be able to publish inappropriate content or use their bandwidth I thought I would at least get the ball rolling. The part of the script in red is a great place to look at integrating with other systems. Notice that in the if statement that I am simply looking for the string “fmle” this should really be a more robust solution but it will work for this simple example.

In the preceding code onAppStart does just that it fires when the application starts. The onConnect fires when a client connects to this application. Finally onPublish fires when someone tries to publish a stream to the server.

There are two parameters the first is the client object that represents the client publishing the stream to the server. The second is a reference to the stream that the client is attempting to publish. Even though I am not going to cover it in this article it is worth mentioning that you can use the stream reference to publish a stream from one server to another in the event that you want to propagate a stream across a number of servers.

What will happen when someone tries to publish a stream to an application that has this “main.asc” in the application folder? If they do not add “logon=fmle” to the connection they will be disconnected (see script in red above).  Most people do not want to stop all Flash Media Live Encoders from publishing to their server they just want to make sure that the right users can publish to their server. In this example the way that we do that is to make sure that who ever attempts to publish to the server includes “fmle” in the querystring. This has to happen from the Flash Media Live Encoder or for that matter any encoder that you are using to publish to the server. In this example I am going to use the Flash Media Live Encoder.  The following is a screen shot of the Flash Media Live Encoder’s output panel:

Flash Media Live Encoder Output Panel
Flash Media Live Encoder Output Panel

Substitute your server dns name or ip address for localhost in the preceding screenshot. There are two elements that you need to be aware of in the preceding. First notice that “foo” is after the last forward slash “foo” represents the  application name which is the same as the name of the directory where “main.asc” is located (see first screenshot). Second notice that after the stream name there is the following “?logon=fmle” this is the querystring. This querystring is initially extracted by using publishQueryString property of the stream object (see blue script above). This represents the entire querystring which often includes other parameters. Since we are only interested in the “logon” parameter we pass the querystring to extractQueryString(see green script above). This function parses the query string and returns the term and value of the term we pass into the extractQueryString function (the term that we are passing in is logon and is the second argument in the following script:

logon = extractQueryString(streamObj.publishQueryString, “logon“);

The value of this argument will have to be “fmle” or the attempt to publish will be denied.

That should cover it. If you have questions or comments let me know. I will most likely follow this up with short article about swf verification.