Problem with web.config access-restricted subdirectory

D

David Pyper

Hi,

I have a problem with web.config unsuccessfully controlling access to
a subdirectory. I'm using VS03 and IIS5.0 on NT2K. I have been able
to reproduce this behaviour on two machines (the 2nd being a WXP
machine) and both times I'm having the same result.

I created a simplified example to illustrate the problem. Here's the
directory structure:

/
/Parent
/Parent/Child


In the /Parent directory, I have 3 files: web.config, Login.aspx and
Default.aspx. In Child I just have Default.aspx. In both directories
there's a bin/ directory that contains Parent.dll and Child.dll (I'm
using code-behind files). Only Login.aspx has a code-behind (in vb)
which I'll show below.

Here's the code from /Parent/web.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation defaultLanguage="vb" debug="true" />
<customErrors mode="RemoteOnly" />
<authentication mode="Forms">
<forms loginUrl="/Parent/Login.aspx" />
</authentication>
<authorization>
<deny users="?" />
<allow users="*" />
</authorization>
<trace enabled="false" requestLimit="10" pageOutput="false"
traceMode="SortByTime" localOnly="true" />
<sessionState
mode="InProc"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data
source=127.0.0.1;Trusted_Connection=yes"
cookieless="false"
timeout="20"
/>
<globalization requestEncoding="utf-8" responseEncoding="utf-8" />
</system.web>
<location allowOverride="false" path="Child">
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</location>
</configuration>


And now here's the contents of /Parent/Default.aspx:

<%@ Page Language="vb" AutoEventWireup="false"
Codebehind="Default.aspx.vb" Inherits="Parent._Default" trace="True"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<title>Default Page</title>
<meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema"
content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body>
<form id="Form1" method="post" runat="server">
This is the default page.
</form>
</body>
</HTML>


And now the content of /Parent/Login.aspx:


<%@ Page Language="vb" AutoEventWireup="false"
Codebehind="Login.aspx.vb" Inherits="Parent.Login" trace="True"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<title>Login Page</title>
<meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema"
content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body>
<form id="Form1" method="post" runat="server">
<asp:TextBox id="txtUser" runat="server">Username</asp:TextBox>
<asp:TextBox id="txtPassword" runat="server">Password</asp:TextBox>
<asp:Button id="btnSubmit" runat="server"
Text="Submit"></asp:Button>
</form>
</body>
</HTML>


And now the code for /Parent/Login.aspx.vb:


Imports System.Web.Security

Public Class Login
Inherits System.Web.UI.Page

#Region " Web Form Designer Generated Code "

'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()

End Sub
Protected WithEvents txtUser As System.Web.UI.WebControls.TextBox
Protected WithEvents txtPassword As
System.Web.UI.WebControls.TextBox
Protected WithEvents btnSubmit As System.Web.UI.WebControls.Button

'NOTE: The following placeholder declaration is required by the
Web Form Designer.
'Do not delete or move it.
Private designerPlaceholderDeclaration As System.Object

Private Sub Page_Init(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form
Designer
'Do not modify it using the code editor.
InitializeComponent()
End Sub

#End Region

Private Sub btnSubmit_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnSubmit.Click

FormsAuthentication.RedirectFromLoginPage(txtUser.Text, False)

End Sub

End Class



And now finally /Parent/Child/Default.aspx:

<%@ Page Language="vb" AutoEventWireup="false"
Codebehind="WebForm1.aspx.vb" Inherits="Child._Default" trace="True"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<title>WebForm1</title>
<meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema"
content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body>
<form id="Form1" method="post" runat="server">
This is the default child page.
</form>
</body>
</HTML>


So to re-iterate, only Login.aspx has any code-behind functionality.
Now that all that's all clear, here's what happens. When I access
/Parent/Default.aspx, I am redirected to
http://localhost/Parent/Login.aspx?ReturnUrl=/Parent/Default.aspx,
which is what I expected would happen. I click btnSubmit and a cookie
is set (.ASPXAUTH) and I'm redirected to /Parent/Default.aspx, also as
expected. Now the problem: when I access /Parent/Child/Default.aspx,
I'm redirected back to
http://localhost/Parent/Login.aspx?ReturnUrl=/Parent/Child/Default.aspx
and prompted for the login again. That's unexpected. I expect that
once I login to /Parent/Login.aspx I should be able to access
/Parent/Child/Default.aspx. But even when I re-login to
/Parent/Login.aspx, the redirect still brings me back to
http://localhost/Parent/Login.aspx?ReturnUrl=/Parent/Child/Default.aspx.

Can someone please shed some light here? What am I not getting?

Thanks!

(e-mail address removed)
 
D

David Pyper

Hernan,

Thanks for your advice. I read the article and tried to implement its
recommendations, but without any success. I also tried your
recommendation of removing the <location> tags but that didn't produce
any results either.

I am starting to believe that the <location> tag does not do what its
documentation says it can do. No matter what I try to do, I can't
seem to get back to my Child/Default page.

I would really appreciate hearing from anyone who can shed more light
on implementing the <location> tag in a parent IIS application
directory and have it successfully control a child IIS application
directory. The documentation yields a lot of promise but the reality
seems to be somewhat less.

Thanks,

David
 
D

David Pyper

Hi,

This message is intended for anyone that happens to read this thread
in an attempt to implement web.config's <location> restriction. The
problems I had were due to the fact that while web.config can impose
its restrictions on a subdirectory, it cannot do so on a subdirectory
that has its own assembly. In order to successfully impose access
restrictions to subdirectories, the served content has to share the
same assembly (typically located in /bin).

To illustrate this, you create an IIS application either through
Visual Studio or through Internet Services Manager. The web.config
should be modified to include a section that looks like the following:

<authentication mode="Forms">
<forms loginUrl="/Parent/Login.aspx" />
</authentication>

<authorization>
<deny users="?" />
<allow users="*" />
</authorization>

Then (and this is where I went wrong) you create a subdirectory in
/Parent (either through Explorer, Visual Studio, -- right-click on
project in Solution Explorer, select Add then New Folder, and name it
what you want -- or however else you create subdirs) and then add your
served content (like .aspx files). Here's my /Parent/Default.aspx:

<%@ Page Language="vb" AutoEventWireup="false"
Codebehind="Default.aspx.vb" Inherits="Parent._Default" trace="True"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<title>Default</title>
<meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema"
content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body>
<form id="Form1" method="post" runat="server">
This is the default page.
</form>
</body>
</HTML>

And now /Parent/Login.aspx

<%@ Page Language="vb" AutoEventWireup="false"
Codebehind="Login.aspx.vb" Inherits="Parent.Login" trace="True"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<title>Login</title>
<meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema"
content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body>
<form id="Form1" method="post" runat="server">
<asp:Button id="btnLogin" runat="server" Text="Login"></asp:Button>
</form>
</body>
</HTML>

And now the code-behind of /Parent/Login.aspx:

Imports System.Web.Security

Public Class Login
Inherits System.Web.UI.Page

#Region " Web Form Designer Generated Code "

'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()

End Sub
Protected WithEvents btnLogin As System.Web.UI.WebControls.Button

'NOTE: The following placeholder declaration is required by the
Web Form Designer.
'Do not delete or move it.
Private designerPlaceholderDeclaration As System.Object

Private Sub Page_Init(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form
Designer
'Do not modify it using the code editor.
InitializeComponent()
End Sub

#End Region

Private Sub btnLogin_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnLogin.Click

FormsAuthentication.RedirectFromLoginPage(Session.SessionID.ToString,
False)

End Sub

End Class

And finally the access-restricted /Parent/Child/Default.aspx file:

<%@ Page Language="vb" AutoEventWireup="false"
Codebehind="Default.aspx.vb" Inherits="Parent._Default1"
trace="True"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<title>Default</title>
<meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema"
content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body>
<form id="Form1" method="post" runat="server">
This is the default child page.
</form>
</body>
</HTML>

Any attempt to access /Parent/Child/Default.aspx without being
authenticated redirects you to /Parent/Login.aspx. Click the Login
button, and you're now authenticated and redirected to
/Parent/Child/Default.aspx. Works like clockwork.

I hope that helps. I wish the documentation on web.config made that
clearer, it could have saved me a lot of grief. For some reason this
distinction, if made, is not clear and the point is not made despite
that I suspect it's a common problem for many.

Good luck!

David
 

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

No members online now.

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,812
Latest member
GracielaWa

Latest Threads

Top