ArcIMS makes an interesting datasource for ArcMap clients, but I have a hard time liking its login options. That is, it just really doesn’t integrate well with — oh — just about any existing security system.
This is a little mockup showing how you can proxy ArcIMS traffic through an ASP.Net HttpHandler. Moreover, this shows how to force ArcMap clients to authenticate.
I’ve removed much of the guts, but it works. Please forgive the screwy code styling. I’m still learning this blogging thing.
Basic Setup
Create a virtual directory “servlet” as an IIS application, and add the below files there.
Enable basic authentication, but keep anonymous access on.
Add a mapping for “.Esrimap” to .NET’s “aspnet_isapi.dll” handler.
WEB.CONFIG
<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"><
appSettings><add key="RemoteWebSite" value="10.147.156.69:8080"/></appSettings>
<system.web>
<compilation defaultLanguage="c#" />
<authentication mode="Windows"/>
<httpHandlers> <add verb="*" path="com.esri.esrimap.Esrimap" type="Proxy, App_Code"/> </httpHandlers>
</system.web>
</configuration>
PROXY.CS
using System;
using System.Configuration;using System.Web;
using System.Net;using System.Text;
using System.IO; /// <summary>/// Web Proxy for ArcIMS traffic that employs ASP.NET Authentication mechanisms
/// </summary>public class Proxy : IHttpHandler
{
public void ProcessRequest(HttpContext context){ // Grab our real ArcIMS server's information from the web.config filestring remoteWebSite = ConfigurationManager.AppSettings["RemoteWebSite"];string remoteUrl = "http://" + remoteWebSite + context.Request.RawUrl;
// Convince ArcMap clients to send credentials
if (!context.Request.IsAuthenticated && context.Request.QueryString.ToString() != "cmd=ping"){context.Response.Status = "401 Unauthorized";context.Response.Write("<?xml version=\"1.0\"?>n<ARCXML><RESPONSE><ERROR>You are not authorized to access this ArcIMS Service.</ERROR></RESPONSE>n</ARCXML>");context.Response.End();
return;}
// Create a web connection to the real ArcIMS server
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(remoteUrl);request.Method = context.Request.HttpMethod;
// Post any ArcXML to the real ArcIMS server
if (context.Request.HttpMethod == "POST"){Stream sendStream = request.GetRequestStream();byte[] buff2 = new byte[1024];
int bytes2 = 0;while ((bytes2 = context.Request.InputStream.Read(buff2, 0, 1024)) > 0){sendStream.Write(buff2, 0, bytes2);
}
sendStream.Close();
}
// Recieve an ArcXML response from the real ArcIMS server
HttpWebResponse response = (HttpWebResponse)request.GetResponse();Stream receiveStream = response.GetResponseStream();byte[] buff = new byte[1024];int bytes = 0;
while ((bytes = receiveStream.Read(buff, 0, 1024)) > 0){context.Response.OutputStream.Write(buff, 0, bytes);
}
response.Close();
context.Response.End();
}
public bool IsReusable{get
{
return true;}}
}