Authentication condition in custom httphandler

S

ScottB

I’m working on an ASP.Net application that uses forms authentication and I
could use some help. I need to build some custom HTTPHandlers to handle
security on some word documents that I have on my website. I’ve created a
class named DocHandler (see the code below, thanks Atal Bihari Upadhyay)
which implements the IHTTPHandler interface. My problem is this: In the
ProcessRequest subprocedure, I want to create a condition that is based on
the User.Identity.IsAuthenticated property for the application but I’m not
sure how to expose or reference it. Ideally, the condition should say that
if the user is authenticated, then the user will have access to the word
document (*.doc). If the user tries to access the file without
authentication, they will get a message that says “Access denied, please
login properly!â€.


Imports System.Web
Imports System.Web.Security.FormsAuthentication

Namespace SpecialHTTPHandler

Public Class DocHandler
Implements IHttpHandler

Public Sub ProcessRequest(ByVal context As HttpContext) Implements
IHttpHandler.ProcessRequest
If User.Identity.IsAuthenticated Then
context.Response.Buffer = True
context.Response.Clear()
context.Response.AddHeader("content-disposition", "attachement;
filename=x.doc")
context.Response.ContentType = "application/doc"
context.Response.WriteFile("pp.doc")
Else
context.Response.Write("Access denied, please login properly!")
End If
End Sub

Public ReadOnly Property IsReusable() As Boolean Implements
IHttpHandler.IsReusable
Get
Return True
End Get
End Property
End Class
End Namespace


This problem has exceeded my level of experience so any help will be greatly
appreciated. Thanks in advance for your help.
 
J

Joe Kaplan \(MVP - ADSI\)

Wouldn't it be easier to let the UrlAuthorizationModule do this for you?
You could then just set up the security in the web.config with allow and
deny tags.

If you need to code it yourself, reverse engineering the
UrlAuthorizationModule will help you understand how they do it. As I recall
they just set the response status to 401 and call CompleteRequest.

The User, Request and Response should all be members of the HttpContext you
get from ProcessRequest method.

Joe K.
 
S

ScottB

I haven't used the UrlAuthorizationModule before but as I understand it, I
don't think that it is the right fit for this issue. There are hundreds of
word documents through out the site. Also, the documents are changeing all
the time so revising the web.config file would be labor intensive. Also,
user credentials are set up in a SQL database where there could be 100s, even
1,000s of users.

I just think it would be much smoother to just give authenticated users
access to all posted .doc downloads. By the way, I also will be posting
..pdf, .xls, and others. Let me know if I'm not looking at it from the right
direction. Thanks for your reply, I appreciate it.

Scott Bass
 
J

Joe Kaplan \(MVP - ADSI\)

In that case, just check Context.User.Identity.IsAuthenticated. Then, you
can either redirect them to a logon page or just set the response status
code to 401 and exit out of the handler. If you are using Forms
authentication, the 401 should land you back at the logon page.

However, I still think you can do this without any custom handlers and just
using config. Using the built-in StaticFileHandler should allow you to
direct requests for specific file extensions to ASP.NET. Then, if you put
the static files in a sub-directory, you would then be able to set up a
location tag in your web.config that only allows access to authenticated
users. ASP.NET will do the rest.

If you need to dynamically stream or generate the files, then a custom
handler might needed, but otherwise the built in stuff can do all this with
no coding.

Another thing you might consider is a custom HttpModule that does the
authorization. It would just look for your protected resources by
extension, check the authenticated status and stop the request if need be as
above. You'd still need the same bit with the StaticFileHandler, but you
wouldn't need to use the web.config for the authorization.

Joe K.
 
S

ScottB

Joe,

Thanks again for the reply. I appreciate your staying with this problem. I
tried the Context.User.Identity.IsAuthenticated property as a condition in
the If statement and it worked. The problem now is with the line
“context.Response.WriteFile(“pp.docâ€)â€. I got the code for the HTTPHandler
on one of the website forums. I actually saw the code in 2 locations.

Anyway, the HTTPHandler fires off OK but I get an error message that says
the system can’t find the file “pp.docâ€. I don’t have the experience with
this stuff but I thought “pp.doc†was used to describe any .doc file. So, I
change the “pp.doc†to the name of the test file just to see what happens.

The file was opened in the browser, showing all the characters, including
the formatting characters. This is not what I’m trying to do for 2 reasons.
The first, is that I would have to write a HTTPHandler for every file and the
second, is that I want the file to be opened in Microsoft Word.

So, I tired using the built-in StaticFileHandler and that didn’t work
either. I changed the HTTPHandlers in the web.config to the following:

<httpHandlers>
<add verb="*" path="*.doc" type="System.Web.StaticFileHandler" />
<add verb="*" path="*.pdf" type="System.Web.StaticFileHandler" />
</httpHandlers>

I added the location element to the web.config and it also didn’t work. By
not working, I mean that you can open the .doc or .pdf files without having
to authenticate. One thing confuses me about adding the location element.
Within the web.config file, I have Authentication set up for Forms and
Authorization set to Deny Unauthenticated Users. This should cover us for
the complete website so I’m not sure why we would need the location tag.
But, even so, I added it and it still did not work.

This is very frustrating but I really appreciate you staying with me on
this. In a nutshell, here is what I want to accomplish.

I have a website with a single ASP.Net application. The application has
subdirectories. Within these subdirectories I will have lots of .doc and
..pdf files. Authentication is set to Forms with Authorization set to Deny
Unauthorized Users. I’m authenticating against a SQL database. I don’t want
the users to have access to the .doc or .pdf files unless they authenticate.
There is no persistent cookie generated so the user has to login each time.
When the user accesses a .doc file, I want Microsoft Word to open and when
the user accesses a .pdf file, I want Acrobat Reader to open.

At this point, when I access .aspx pages, everything works like a champ.
When I access any .doc or .pdf file outside of the application, I go right to
the file with no request to authenticate.

I’m pulling my hair out on this one. This is such a basic requirement of
any website and I know I’m missing something that is real stupid so any help
will be appreciated.

Scott Bass
 
J

Joe Kaplan \(MVP - ADSI\)

Hi Scott, did you map the .doc and .pdf extensions to ASP.NET in the IIS
metabase mappings for your app? It sounds like the .doc and .pdf files
aren't being processed by ASP.NET for some reason. The StaticFileHandler
and <allow>/<deny> tags should be able to do everything you want.

You are correct that you don't need the location tag if the entire site is
supposed to be authenticated. For some reason I got the idea that you had a
mix of anonymous and authenticated content.

Joe K.
 
S

ScottB

Joe,

I've made the proper mappings in IIS to the aspnet_isapi.dll for both the
..doc and .pdf as well as the mappings to the StaticFileHandler in the
<httpHandler> section of the web.config. Although, the only attributes
within the <httphandler> section that I'm aware of are verb, type, and path.
Where would the <allow>/<deny> tags go? Thanks.
 
J

Joe Kaplan \(MVP - ADSI\)

Sorry for the delay.

The authorization tags should be in the system.web section like this:

<configuration>
<system.web>
<authorization>
<allow users="?"/>
<deny users="*"/>
</authorization>
</system.web>
</configuration>

This essentially says "allow access to the entire site for authenticated
users, but deny access to everyone else. If you need to have different
settings at different locations in the app, you need to use the location
tag.

Does this help?

Joe K.
 
S

ScottB

Joe,

The authorization has never been a problem. But I did find a solution for
you to check out. A friend had mentioned the HTTPContext class and the
Request.Url property and that was enough to get me going in the right
direction. I went ahead and took the AbsolutePath property of the Uri object
and plugged that into the WriteFile method to make each handler generic.
I’ve included the code to show you the simplicity. This should give anyone
the base from which to put in any refinements that they will need.

Web.config changes

<httpHandlers>
<add verb="*" path="*.doc"
type="ExtraHTTPHandlers.ExtraHandlers.DocHandler, ExtraHTTPHandlers" />
<add verb="*" path="*.pdf"
type="ExtraHTTPHandlers.ExtraHandlers.PDFHandler, ExtraHTTPHandlers" />
<add verb="*" path="*.htm" type="System.Web.UI.PageHandlerFactory" />
<add verb="*" path="*.html" type="System.Web.UI.PageHandlerFactory" />
</httpHandlers>

HTTPHandler for all .doc

Imports System.Web

Namespace ExtraHandlers
Public Class DocHandler
Implements IHttpHandler

Public ReadOnly Property IsReusable() As Boolean Implements
System.Web.IHttpHandler.IsReusable
Get
Return True
End Get
End Property

Public Sub ProcessRequest(ByVal context As System.Web.HttpContext)
Implements _ System.Web.IHttpHandler.ProcessRequest
Dim UserDocRequest As Uri = context.Request.Url
Dim strDocUrl As String = UserDocRequest.AbsolutePath
If context.User.Identity.IsAuthenticated Then
context.Response.Buffer = True
context.Response.Clear()
context.Response.AddHeader("content-disposition",
"attachement; filename=iwi.doc")
context.Response.ContentType = "application/doc"
context.Response.WriteFile(strDocUrl)
Else

context.Response.Redirect("http://www.iwiwebapp.com/agentcenter/agentlogin.aspx")
End If
End Sub
End Class
End Namespace

HTTPHandler for all .pdf

Imports System.Web

Namespace ExtraHandlers
Public Class PDFHandler
Implements IHttpHandler

Public ReadOnly Property IsReusable() As Boolean Implements
System.Web.IHttpHandler.IsReusable
Get
Return True
End Get
End Property

Public Sub ProcessRequest(ByVal context As System.Web.HttpContext)
Implements _ System.Web.IHttpHandler.ProcessRequest
Dim UserPDFRequest As Uri = context.Request.Url
Dim strPDFUrl As String = UserPDFRequest.AbsolutePath
If context.User.Identity.IsAuthenticated Then
context.Response.Buffer = True
context.Response.Clear()
context.Response.AddHeader("content-disposition",
"attachement; filename=iwi.pdf")
context.Response.ContentType = "application/pdf"
context.Response.WriteFile(strPDFUrl)
Else

context.Response.Redirect("http://www.iwiwebapp.com/agentcenter/agentlogin.aspx")
End If
End Sub
End Class
End Namespace

Scott Bass
 
J

Joe Kaplan \(MVP - ADSI\)

So, the StaticFileHandler never worked? That is weird. I'm not sure what's
up with that. It does something very similar to what you are doing, but it
also includes some caching (and doesn't do the authorization stuff
obviously). You might want to consider some caching if you need to get the
perf to be better.

Best of luck,

Joe K.
 
S

ScottB

Joe,

Unfortunately, the StaticFileHandler did not work although it sure seemed to
be the logical fix in the beginning. Thanks for your help Joe.

Scott Bass
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,233
Latest member
AlyssaCrai

Latest Threads

Top