Khurram Hassan Khurram Hassan - 2 months ago 11
ASP.NET (C#) Question

Custom Authorization for all requests to sub-folder in ASP.NET website

I have a ASP.NET 4.0 website which contains a sub-folder with multimedia files like JPG, PNG, MP4, MP3, etc.

Currently, any user with the full link to the files is able to access the multimedia files without any restriction. I want to find the currently logged in user who is making the request and after checking their permissions from DB allow/disallow them to access the file requested.

I have tried implementing a Custom

HttpModule
for this purpose but I am not able to find the current user making the request. Below is my code:

public class CustomHttpModule : IHttpModule
{
private const string URL_TO_LOOK_FOR = "/MultiMediaFiles/";

public CustomHttpModule()
{ }

public void Init(HttpApplication app)
{
app.AuthenticateRequest += CustomAuthenticateRequest;
//app.EndRequest += CustomAuthenticateRequest;
}

void CustomAuthenticateRequest(object source, EventArgs e)
{
HttpApplication app = (HttpApplication)source;
HttpContext context = app.Context;
Uri url = context.Request.Url;
if (url.AbsolutePath.StartsWith(URL_TO_LOOK_FOR, StringComparison.OrdinalIgnoreCase))
{
var response = context.Response;
response.Clear();
response.Write("app.Context.User :");
if (context.User == null || context.User.Identity == null || context.User.Identity.Name == null)
{
response.Write("No user");
}
else
{
response.Write(context.User.Identity.Name);
}

response.End();
response.Flush();
response.Close();
}
}

public void Dispose()
{ }
}


I tried attaching to events:
BeginRequest
,
AuthenticateRequest
,
PostAuthenticateRequest
and even
EndRequest
, but in each case
context.User
is always
null
even after I have logged in to my website.

EDIT:
I am using the
FormsAuthentication
and my web.config contains:

<system.web>
<authentication mode="Forms">
<forms name="MyWebFORMAUTH" timeout="60"
loginUrl="~/web/logon/default.aspx" cookieless="UseCookies"
defaultUrl="~/web/logon/default.aspx"
slidingExpiration="true" />
</authentication>
</system.web>
<system.webServer>
<modules>
<add name="CustomHttpModule" type="CustomHttpModule"/>
</modules>
<system.webServer>


NOTE: I cannot modify the links to multimedia files.

Please HELP.

Answer

UPDATE:

You would also need to tell ASP.NET that you don't want to execute static content handler for certain file types in certain directory.

Here is the updated version of web.config file:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.web>
        <compilation debug="true" targetFramework="4.0" />
        <httpRuntime />
        <authentication mode="Forms">
            <forms name="MyWebFORMAUTH" timeout="60"
                   loginUrl="~/web/logon/default.aspx" cookieless="UseCookies"
                   defaultUrl="~/web/logon/default.aspx"
                   slidingExpiration="true" />
        </authentication>
    </system.web>
    <system.webServer>
        <modules>
            <add name="CustomHttpModule" type="CustomHttpModule" />
        </modules>
        <defaultDocument>
            <files>
                <clear />
                <add value="Default.aspx" />
            </files>
        </defaultDocument>
    </system.webServer>
    <location path="MultiMediaFiles">
        <system.webServer>
            <handlers>
                <!-- This line tells ASP.NET to skip the processing of PNG files
                     by default static content handler. -->
                <add name="SkipStaticPng" path="*.png" verb="GET"
                     type="System.Web.Handlers.TransferRequestHandler"
                     preCondition="integratedMode,runtimeVersionv4.0" />
            </handlers>
        </system.webServer>
    </location>
</configuration>

Your code should work. Here is the example:

Default.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebForm" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Test</title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:Label ID="CurrentUserLabel" runat="server" />
        <br />
        <asp:Button ID="LoginButton" runat="server" OnClick="LoginButton_Click" Text="Login" />
    </form>
</body>
</html>

Default.aspx.cs:

using System;
using System.Security.Principal;
using System.Web.Security;

public partial class WebForm : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
            PopulateCurrentUserName();
    }

    protected void LoginButton_Click(object sender, EventArgs e)
    {
        FormsAuthentication.SetAuthCookie("test_user", false);
        Response.Redirect(Request.Url.AbsoluteUri);
    }

    private void PopulateCurrentUserName()
    {
        IPrincipal user = Request.RequestContext.HttpContext.User;
        if (user != null && user.Identity != null && !String.IsNullOrEmpty(user.Identity.Name))
            CurrentUserLabel.Text = user.Identity.Name;
        else
            CurrentUserLabel.Text = "(null)";
    }
}

CustomHttpModule.cs:

using System;
using System.Web;

public class CustomHttpModule : IHttpModule
{
    private const string URL_TO_LOOK_FOR = "/MultiMediaFiles/";

    public CustomHttpModule()
    {
    }

    public void Init(HttpApplication app)
    {
        app.AuthenticateRequest += CustomAuthenticateRequest;
    }

    void CustomAuthenticateRequest(object source, EventArgs e)
    {
        HttpApplication app = (HttpApplication)source;
        HttpContext context = app.Context;
        Uri url = context.Request.Url;
        if (url.AbsolutePath.StartsWith(URL_TO_LOOK_FOR, StringComparison.OrdinalIgnoreCase))
        {
            var response = context.Response;
            response.Clear();
            response.Write("app.Context.User :");
            if (context.User == null || context.User.Identity == null || context.User.Identity.Name == null)
            {
                response.Write("No user");
            }
            else
            {
                response.Write(context.User.Identity.Name);
            }

            response.End();
            response.Flush();
            response.Close();
        }
    }

    public void Dispose()
    {
    }
}

web.config:

<?xml version="1.0"?>
<configuration>
    <system.web>
        <compilation debug="true" targetFramework="4.0"/>
        <httpRuntime/>
        <authentication mode="Forms">
            <forms name="MyWebFORMAUTH" timeout="60"
                   loginUrl="~/web/logon/default.aspx" cookieless="UseCookies"
                   defaultUrl="~/web/logon/default.aspx"
                   slidingExpiration="true" />
        </authentication>
    </system.web>
    <system.webServer>
        <modules>
            <add name="CustomHttpModule" type="CustomHttpModule"/>
        </modules>
        <defaultDocument>
            <files>
                <clear/>
                <add value="Default.aspx"/>
            </files>
        </defaultDocument>
    </system.webServer>
</configuration>

And here is the test scenario:

  1. Clear the cookies in your browser.
  2. Navigate to the start page (let's say it is http://localhost).
  3. You will see that current user is (null).
  4. Open http://localhost/MultiMediaFiles/ in the second tab.
  5. You will see the "app.Context.User :No user" message.
  6. Switch back to the previous tab and click "Login" button.
  7. You will see that current user now is "test_user".
  8. Switch to the second tab and refresh the page.
  9. If everything is correct then the "app.Context.User :test_user" message should be displayed.
Comments