Question

We're building a web application that is secured using Forms Authentication. On a certain page, we have a list of thumbnails. These thumbnails are generated with ImageResizer like this:

<img src="/Data/Pictures/image01.jpg?width=100" />

This was all working fine during development using the built in web server of Visual Studio 2010. When we deployed the application to our production server (running Windows 2008 and IIS 7.5) we noticed the thumbnails weren't working anymore. When switching our development build to IIS Express instead of Cassini, we had the same problem.

  1. When navigating to /Data/Pictures/image01.jpg directly (when logged in), we can see the image.

  2. When navigating to /Data/Pictures/image01.jpg?width=100 directly (when logged in), we get this error message:

    Server Error in '/' Application.

    This type of page is not served.

    Description: The type of page you have requested is not served because it has been explicitly forbidden. The extension '.jpg' may be incorrect. Please review the URL below and make sure that it is spelled correctly.

    Requested URL: /Data/Pictures/image01.jpg

  3. When navigating to /Data/Pictures/image01.jpg.ashx?width=100 directly (when logged in), we can see the resized image.

A workaround for the problem was excluding the pictures directory from Forms Authentication like this:

<location path="Data/Pictures">
    <system.web>
        <authorization>
            <allow users="*" />
        </authorization>
    </system.web>
</location>

Now the thumbnails are visible again, but I don't feel quite right about this workaround.

I have sumbitted a support ticket on the site of the ImageResizer and asked why images without a querystring work and the ones with a querystring don't. The author of ImageResizer replied and he told me:

Because the ImageResizer doesn't handle non-processed images, those are handled by IIS. You need to duplicate your rules in to protect static content: http://www.iis.net/ConfigReference/system.webServer/security/authorization

I have read that page and I have tried to duplicate our authentication and authorization settings to the <security> element inside <system.webServer> but I wasn't able to solve it this way.

What can we do to solve this problem?

Update

I have deployed the application to two of our production servers and they both have the same issue. We also have the issue on two developer machines in IIS Express. Our production servers aren't necessarily indentical in configuration (I'm not sure of this, but I assume there have to be some minor differences). So I guess (actually, I hope :-)) the cause can be found in the Web.Config file below:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <configSections>
        <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.3.1.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
        <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
            <section name="MyApp.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
        </sectionGroup>
        <section name="resizer" type="ImageResizer.ResizerSection" />
        <section name="dotless" type="dotless.Core.configuration.DotlessConfigurationSectionHandler, dotless.Core" />
    </configSections>
    <connectionStrings>
        <add name="MyAppContext" connectionString="xxx" providerName="System.Data.SqlClient" />        
    </connectionStrings>
    <system.web>
        <pages validateRequest="false" />
        <httpRuntime requestValidationMode="2.0" />
        <globalization requestEncoding="utf-8" responseEncoding="utf-8" culture="nl-BE" uiCulture="nl-BE" />
        <authentication mode="Forms">
            <forms loginUrl="~/Default.aspx" timeout="480" />
        </authentication>
        <authorization>
            <deny users="?" />
        </authorization>
        <compilation debug="true" targetFramework="4.0" />
    </system.web>
    <entityFramework>
        <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework">
            <parameters>
                <parameter value="Data Source=.\SQLEXPRESS; Integrated Security=True; MultipleActiveResultSets=True" />
            </parameters>
        </defaultConnectionFactory>
    </entityFramework>
    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity name="Yahoo.Yui.Compressor" publicKeyToken="f8b4b81ec75097e2" culture="neutral" />
                <bindingRedirect oldVersion="0.0.0.0-1.7.1.0" newVersion="1.7.1.0" />
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="AjaxMin" publicKeyToken="21ef50ce11b5d80f" culture="neutral" />
                <bindingRedirect oldVersion="0.0.0.0-4.51.4507.18296" newVersion="4.51.4507.18296" />
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="dotless.Core" publicKeyToken="96b446c9e63eae34" culture="neutral" />
                <bindingRedirect oldVersion="0.0.0.0-1.3.0.3" newVersion="1.3.0.3" />
            </dependentAssembly>
        </assemblyBinding>
    </runtime>
    <system.webServer>
        <validation validateIntegratedModeConfiguration="false" />
        <modules>
            <add name="ImageResizingModule" type="ImageResizer.InterceptModule" />
        </modules>
        <handlers>
            <add name="dotless" path="*.less" verb="GET" type="dotless.Core.LessCssHttpHandler,dotless.Core" resourceType="File" preCondition="" />
        </handlers>
    </system.webServer>
    <location path="Assets">
        <system.web>
            <authorization>
                <allow users="*" />
            </authorization>
        </system.web>
    </location>
    <location path="Data/Pictures">
        <system.web>
            <authorization>
                <allow users="*" />
            </authorization>
        </system.web>
    </location>
    <dotless minifyCss="false" cache="true" web="false" />
</configuration>
Was it helpful?

Solution

ImageResizer is designed to integrate properly with ASP.NET URL authorization in the default install of IIS 5, IIS 5.1, IIS 6, IIS 7, IIS 7.5, Cassini, and IIS Express.

However, there are at least a dozen permutations available on IIS7 & IIS 7.5. You can selectively install or uninstall, (as well as enable or disable) the IIS 6 Legacy, IIS 7, ASP.NET 2, and ASP.NET 4 Url Authorization modules. And there's integrated mode or classic mode. And in classic mode, it's all extension-based, meaning they could be customized or there could be a wildcard mapping. Then there is the RAMMFAR attribute, RunAllManagedModulesForAllRequests. Also, you can set preconditions on the several individual UrlAuthorizationModules to control which extensions they execute for. Each of these variables affects which of the 4 URL Authorization engines control which file types, and one or more of these variables is set up wrong.

Now, on a clean install, ImageResizer can ensure everything is handled properly; all images go under ASP.NET rule, following the ASP.NET Authentication and Authorization rules. But there are an awful lot of ways mess up Url Authorization, and without knowing what modules are installed and enabled in IIS, and seeing a full copy of your Web.config, I can't know why ASP.NET UrlAuthorization isn't getting applied consistently.

ImageResizer acts minimalistically - unless an image has a querystring, and that querystring has recognized commands, ImageResizer will not do anything to it. Thus, only processed images are being 'forced' to follow the ASP.NET Url Authorization rules.

By default, the untouched requests (without querystring commands) should be following the ASP.NET rules as well, assuming you're running in Integrated mode. However, something is wrong with your install or configuration. "This type of page is not served." is a known 403 message for IIS, but it also typically means things aren't configured correctly. The fact that static files aren't following the ASP.NET rules is another indicator of a configuration issue.

An easy way to verify it's a OS/IIS configuration issue would be to start up a labslice virtual machine (Only costs a quarter), and put your software on there. If you see the problem again, you know it's in Web.config. If not, it's IIS/Machine.config or OS level.

You've already stated one solution - add URL Authorization exceptions for images so ImageResizer doesn't require authentication to display them.

OTHER TIPS

I had similar problem: Image Resizer worked fine on local but not on server. It was because classic pipeline is used on this project. My solution: Add this the Web.config

   <resizer>
    <pipeline fakeExtensions=".axd" defaultCommands="autorotate.default=true"/>
    <plugins>
      <add name="DiskCache" />
      <add name="PrettyGifs" />
      <add name="MvcRoutingShim" />
    </plugins>
  </resizer>
..
 <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <modules>
      <!-- This is for IIS7/8 Integrated mode -->
      <add name="ImageResizingModule" type="ImageResizer.InterceptModule"/>
    </modules>
  </system.webServer>

and add this to the image links :

+ ".axd?height=165&width=297&mode=crop";
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top