Republished with Permission - Original Article
Problem: You are developing/maintaining an
ASP.NET web-site, and would like the ability to conditionally show/hide runtime
error messages depending on who the user visiting the site is.
For a normal user visiting the site you want
to be able to display a friendly error message like this when a runtime error
occurs:
Figure 1
But when someone within the “developers” security role of
your application remotely accesses the site you want to instead show a more
detailed exception stack trace error message about the problem without having
to change any configuration data:
Figure 2
The below post describes how to use ASP.NET’s role-based
security architecture in conjunction with the Global.asax Application_Error
event handler to enable this. You can also download
a sample I’ve built that shows how to implement this here.
Some Background Discussion on Error Handling and ASP.NET
Custom Error Pages:
ASP.NET and .NET support a rich error-handling architecture
that provides a flexible way to catch/handle errors at multiple levels within
an application. Specifically, you can catch and handle a runtime
exception with a class, within a page, or on the global application level using
the Application_Error event handler within the Global.asax class. If a
runtime exception isn’t handled/cancelled by one of these mechanisms, then
ASP.NET’s Custom Error Page feature will kick-in, and an error page will be
sent back to the browser accessing the application.
ASP.NET’s Custom Error Page feature can be used to configure
a “friendly error page” to be displayed to end-users in place of the standard
“server error occurred” message sent back by ASP.NET. For example, the
below web.config file section will cause remote users visiting the site to be
redirected to a “friendlyErrorPage.htm” file anytime a runtime error occurs
(note: HTTP 500 status code responses indicate runtime errors on the server):
Listing 1
<customErrors mode="RemoteOnly">
<error statusCode="500" redirect="friendlyErrorPage.htm"/>
</customErrors>
To learn more about how the ASP.NET Custom Errors feature
works, and how to configure it, please review this
article.
Important: I would recommend never setting the
<customErrors> mode attribute to “Off”. Doing this will cause
detailed error messages to be sent back to all normal users visiting your
site. This can lead to information disclosure issues that can compromise
the security of your site. Instead, only change this setting to “On” or
“RemoteOnly” (the default) and use the technique below for cases where you want
to display detailed error messages to only some users.
Solution:
The above <customErrors> configuration section will
cause a friendly error message to be sent to the browser anytime a runtime
error message occurs. This is what we want to happen anytime a normal
user access the site, and will allow us to display error pages like this:
Figure 3
To enable developers to instead see detailed
error messages when they access the site, I can then add this code to the
Application_Error event handler within the Global.asax class:
Listing 2
Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
If (Context IsNot Nothing) And (Context.User.IsInRole("Developer")) Then
Dim err As Exception = Server.GetLastError()
Response.Clear()
Response.Write("<h1>" & err.InnerException.Message & "</h1>")
Response.Write("<pre>" & err.ToString & "</pre>")
Server.ClearError()
End If
End Sub
The above code checks to see if the current
user visiting the site is within a specific security role. If so, then it
retrieves the exception raised during the current request via the
Server.GetLastError() method. It then clears out any content already
generated during the current request, and instead outputs the Exception details
to the response. Lastly, it clears out the Exception from the request –
which will prevent ASP.NET’s custom error architecture from kicking in.
The result instead is a page that details the error like so:
Figure 4
To learn more about how you can easily create and manage a
“Developer” role like the one I’m using above, please review my previous post: Implementing
Role Based Security with ASP.NET using Windows Authentication and SQL Server.
If you don’t want to store your role-mappings within a database, you can also
store them within Active Directory or your own custom role-provider.
This
sample demonstrates using a Windows User’s membership within the local
“Administrators” group on a machine to control whether or not the detailed
error message is displayed. Note: you can perform a role-check on a local
Windows group by writing: User.IsInRole(“BUILTIN\Administrators”) – where the
“BUILTIN” prefix indicates that it is a local group as opposed to a domain
level one).
Hope this helps,
Scott