For a number of years now I've had customers ask me about how to prevent deep linking from random people directly to their Windows Media server.  Deep linking is described on http://en.wikipedia.org/wiki/Deep_linking.  Often this occurs when a web site owner does not ask for permission to point an embedded media player on their own site to a stream on someone else’s Windows Media server.  The web site owners who host their own Windows Media servers may want to allow only those clients that visit their web site access to the WMS server.  They may also want to have their client authenticate with a user name and password to be able to stream the video content.

Let me stop right here and say that the sample code that I’m providing is just that.  It’s sample code.  No warranty expressed or implied.  You’re on your own.  Let me also say that this is not going to keep your content 100% double extra secure.  It is just an easy *somewhat* secure way of preventing deep linking.  If you want high security, look into the Windows Media Rights Manager SDK.

Typically what I have recommended in the past is using an authorization plug-in running in WMS.  Essentially you would generate a query string on your web server that contains some unique value on the end (example:  mms://streaming.contoso.com/video.wmv?authorization=6883af2234jjji8).  In this example the authorization code of 6883af2234jjji8 would be unique for the session while browsing the web site.  You could then drop that value and a time/date stamp onto a SQL server.  You would write an authorization plug-in for WMS that would take the client request, look up the authorization ID in the SQL server and then allow or disallow the connection.  There are a number of variations on this theme, but typically it’s usually done somewhat like this.

I wanted to do something easier that required much less programming and didn’t have to have special web code or a third server (like SQL) to handle a deep linking issue.  The code example below is an Active Script sample.  Copy the code (or download it from the link below) and save it as a .vbs file in your C:\WMPub folder.  This folder has the appropriate NTFS permissions for WMS to be able to read from the .vbs and write the log file.  Then locate the WMS Active Script Event Handler in the WMS admin under Windows Media Services\<machine name>\Properties\Event notification.  In the Active Script plug-in, browse to the script sample in the WMPub folder.  Note, you will need to make one change to the third line in the script as noted in the comment in the code.  Enable the plug-in and you’re ALMOST done.  The way this script works is by reading the HTTP REFERER header value from the HTTP protocol from the user's GET request.  This GET request is made when you link to the content on your Windows Media server from the HTML page on your web server.  The HTTP REFERER is automatically included in the request.  If the user is not making a request from a web page on your web site, they will be denied access.

NOTE:  This value is not available with RTSP.  That means that you must turn off RTSP for this to work properly.

Here’s the code:

 Dim strMyServer
'Change the www.contoso.com value to the DNS name of your site.
strMyServer = "www.contoso.com"

Dim LogFile

Sub CreateLog
  Dim fso
  Set fso = CreateObject("Scripting.FileSystemObject")
  Set LogFile = fso.CreateTextFile("c:\wmpub\wmroot\AuthorizationLog.txt", True)
End Sub

Sub TraceInformation( strTraceText )
    LogFile.WriteLine( strTraceText )
End Sub

Sub OnWMSPluginInitialize ( ServerCtx )
    CreateLog
    tempStr = "OnWMSPluginInitialize " & Now
    TraceInformation( tempStr )
End sub

Sub OnWMSPluginShutdown ()
    tempStr = "OnWMSPluginShutdown " & Now
    TraceInformation( tempStr )
    LogFile.Close
End sub

Function OnWMSEAuthorizeOpen (UserCtx, PresCtx, CmdCtx)
    Dim strReferer
    'Turning off error checking temporarily while getting the user context.  If there is no
    'referer context value then we do not want to end here with an error.  If there is no
    'referer context value we will fail at the first if statement and return the access denied.
    On Error Resume Next
    strReferer = UserCtx("WMS_USER_REFERER").Value
    On Error Goto 0
   
    tempStr = "Validating " & strReferer & " on " & Now
    Dim DomainName
    DomainName = GetLowerFQDN (strReferer)

    if DomainName = LCase(strMyServer) then
        OnWMSEAuthorizeOpen = &H00000000
        tempStr = tempStr & " - Access Granted"
    else
        OnWMSEAuthorizeOpen = &H80070005
        tempStr = tempStr & " - Access Denied"
    end if
    TraceInformation( tempStr )
End Function

Function GetLowerFQDN(strURL)
    'Strips off the initial http:// or https://
    tempDNS = Mid(strURL, InStr(strURL, "://") + 3)

    'Checks to see if a port number is used after the DNS name and strips that off.
    if Mid(tempDNS, 1, InStr(tempDNS, ":")) <> "" then
        tempDNS = Mid(tempDNS, 1, InStr(tempDNS, ":")-1)
    end if

    'Removes everything after and including the first slash.  What remains should be
    'the DNS name.
    if Mid(tempDNS, 1, InStr(tempDNS, "/")) <> "" then
        tempDNS = Mid(tempDNS, 1, InStr(tempDNS, "/")-1)
    end if
    GetLowerFQDN = LCase(tempDNS)
End Function