views:

182

answers:

1

I have a web application that uses the CDO Message object to email reports.

For example:

Dim objCDO
Set objCDO = Server.CreateObject("CDO.Message")
objCDO.CreateMHTMLBody "http://server/report.asp"

The problem is that when it makes its request to IIS, it does not inherit the ASP session identity of the logged in user i.e. the session variables used to authenticate requests before permitting access to the content are blank. This makes authentication tough, forcing me to add a querystring variable (because as you can see, you cant add a form variable to this request) like:

objCDO.CreateMHTMLBody "http://server/report.asp?userid=xx&password=xx"

SURELY there must be a way of the authorisation in the report to check whether the request came from the local machine i.e. the CDO object in the mailer script, thus negating the need for authentication?

+2  A: 

Just don't do it! For these reasons:-

  • Making a second request back into the server will cause the current thread to block, if you have too many of these you will deadlock the application.
  • CreateHTMLBody internaly uses the WinINET http stack to make the request. This stack is intended for use in client interactive scenarios. In the server scenario it isn't thread-safe.
  • You lose all session context so it can (as you are discovering) make somethings more difficult or less secure. In addition it can create a load of unwanted sessions.

Whilst its true CreateHTMLBody can be very convienient it can also create bloated emails. In the server situation you really need to craft the email with code rather than use this tempting method.

Edit

It seems Jimbo has more general scenarios in mind than just CreateHTMLBody. The general scenario is that a component (over which the consumer has no control) is used in an ASP page (we will designate this the "Client Page") and it makes a subsequent request (potentially via WinINET) to another ASP page (we will designate this the "Service Page"). There is the assumption that the only thing the "Client Page" can control about the usage of the component is the URL supplied to it.

Here are some approaches to avoid or mitigate the issues outlined above.

Handling Locking Problems: Placing the "Client Page" and the "Service Page" in different ASP application would avoid the locking issues. My suggestion would be place the "Client Page" in a different application to the rest of the application and that this new application would be in sub folder of the main application.

Dealing with WinINET issues: Place the new application in its own application pool. If using WinINET in an unsafe manner does cause a problem it doesn't affect the main application process. Indeed placing it in its own process may help avoid such problems. (No guarantees here but its the best you can get to avoiding WinINET issues completely).

Controlling security: Configure the "Service Page" to only accept requests from the "Client Page". There are probably a number of ways to do this but the simplest is to enable IP based security, the requests to the "Service Page" should only be coming from a specific IP or at least a limited set of IP addresses.

Handling authentication: During the main application logon create a volatile cookie containing some unique value. Since the "Client Page" is perceived as a sub-folder of the main application by the browser it will receive this cookie. The "Client Page" can use this cookie to confirm the authenticity of the request and/or pass it in the URL when using the component.

Supressing prolific session creation: Have the "Service Page" call Session.Abandon before it completes its operation.

AnthonyWJones
Woo...I didn't know CreateHTMLBody used the WinINET stack. I'm usually banging at customers not to use XMLHTTP but use ServerXMLHTTP for the same reasons. +1
Kev
Thanks for your response. Sadly, there are many instances of this type of application e.g. using a PDF creation control which also uses a similar GetContentFromURL - instances such as these do not have alternatives.
Jimbo