Thursday, May 5, 2005

Securing Images From Unauthorized Users

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/securing_images_from_unauthorized_users.htm]

Sometimes we want to secure images so that only authorized users can view them. Private images might include proprietary diagrams or images with personal information (perhaps paychecks). The problem is that the nature of images in Html is simply a URL to an already-accessible file. For example, the source code for the Google logo at www.google.com is essentially . The src attribute is a relative path from the google main page, so you can directly view this image at http://www.google.com/intl/en/images/logo.gif.

For a secure image, we want:

  1. The application can access it
  2. The user cannot.

This can't merely be solved by trying to "hide" the images in some directory, because the page's source is public. They can't hide. However, we can use .Net to solve this by:

  1. Store our images in a file only accessible to the application
  2. Use System.Drawing to dynamically create an image from a file
  3. Response out that image to an ImgPage.aspx page
  4. Make an image in our main page, and set its source property to the ImgPage.aspx page.

This technique of dynamically displaying images in a WebForm is based off of MVP Scott Mitchell's article Create Snazzy Web Charts and Graphics On the Fly with the .NET Framework. The conceptual difference is that instead of dynamically creating an image (such as a chart) and outputting it, we're dynamically creating the image simply by loading in an image file.

The first step is easy. The second step requires some coding. The function below resides in ImgPage.aspx.cs. It assumes that you pass in the image file path in any way you see fit. One way is to get the filename from the querystring. For simplicity this method assumes just "gif" images, but you could get the image extension and set the type as appropriate.

private void Page_Load(object sender, System.EventArgs e)
 {
     string strFile = Request.QueryString["img"].ToString();
     SetImage(strFile);
 }
 
 private void SetImage(string strFile)
 {
     //Set Response type for an image
     Response.ContentType = @"image/gif";
 
     System.Drawing.Bitmap bm = null;
     using (bm)
     {
         bm = (Bitmap)Bitmap.FromFile(strFile);
         bm.Save(Response.OutputStream,ImageFormat.Gif);
     }
 }

First we set the page Response's content type. We then create a BitMap from a file, and save it to the Response OutputStream. Note that ImgPage.aspx is an empty page designed solely to receive this output.

Our main page has an image with the source property set to aspx page and its querystring, such as ImgPage.aspx?img=FilePath.gif. The main page code behind can then do whatever it needs to determine the correct querystring.

<asp:Image id="Image1" runat="server" ImageUrl="ImgPage.aspx">asp:Image>

While I've built a proto-type for this, I admit that I haven't tested it in an enterprise application, but it seems pretty promising.

No comments:

Post a Comment