IIS 7 с модулем перезаписи URL 2.0 - установка 401 кодов состояния и ReturnUrl - PullRequest
0 голосов
/ 02 февраля 2011

У меня есть веб-сайт, размещенный на IIS 7 с установленным модулем перезаписи URL 2.0 .Он запускается системой управления контентом, которая просматривает URL-адрес и возвращает ошибку 401, если текущий пользователь не имеет разрешения на просмотр страницы.Это обнаруживается модулем авторизации URL-адреса ASP.NET, который затем перенаправляет страницу на страницу loginUrl, как указано в файле web.config (проверка подлинности форм).

Это отлично работает на моем локальном компьютере, которыйэто IIS 7 и Windows 7.

Если URL, скажем, /612/some-string, пользователь перенаправляется на страницу входа в систему по адресу /66/login?ReturnUrl=/612/some-string.

Переписывание URL-адреса выглядит в первой частиURL для идентификатора документа.Реальный URL будет таким: index.aspx?documentId=612

К сожалению, когда я развернул это на нашем промежуточном сервере, ReturnUrl - это не переписанный URL, а оригинальный URL.Это вызывает всевозможные проблемы.

Промежуточным сервером также является IIS 7 с установленным модулем перезаписи URL 2.0.Это Windows 2008 server SP2.Оба работают под управлением ASP.NET 3.5.

Я могу только предположить, что файл machine.config по-разному упорядочивает httpModules по умолчанию, и модуль аутентификации форм .NET подключается до того, как URL будет перезаписан.

Я скоро рассмотрю, но в то же время, каков опыт с этой проблемой и можно ли ее решить?

Обновление

Я также пытался изменить

Response.StatusCode = 401; 

до

FormsAuthentication.RedirectToLoginPage();

, что немного опережает меня, но все же направляет пользователя обратно на URL, который не был переписан.

Я могутакже сделайте это вместо установки 401:

string currentPage = HttpUtility.UrlEncode(Request.RawUrl);
string loginUrl = FormsAuthentication.LoginUrl + "?ReturnUrl=" + currentPage;
Response.Redirect(loginUrl);

Но это кажется уродливым.

1 Ответ

1 голос
/ 03 апреля 2011

В главе 2 книги «Разработка более = защищенных приложений Microsoft ASP.NET 2.0» Доминика Байера есть ShowPipeline.ashx, который показывает полное упорядочение конвейера на сервере с использованием HttpHandler:

    <%@ WebHandler Class='ShowPipeline' Language='c#' %>

    using System;
    using System.Web;
    using System.Reflection;
    using System.ComponentModel;

    // shows which modules have registered for which event
    // add a ?asm=true query string parameter to also show the assemblies
    public class ShowPipeline : IHttpHandler

    {
        static bool _showAssemblies = false;

        // names of the pipeline events
    static string[] _handlerNames = {
        "BeginRequest",
        "AuthenticateRequest",
        "DefaultAuthentication",
        "PostAuthenticateRequest",
        "AuthorizeRequest",
        "PostAuthorizeRequest",
        "ResolveRequestCache",
        "PostResolveRequestCache",
        "AcquireRequestState",
        "PostAcquireRequestState",
        "PreRequestHandlerExecute",
        "PostRequestHandlerExecute",
        "ReleaseRequestState",
        "UpdateRequestCache",
        "PostUpdateRequestCache",
        "EndRequest"
    };

    public void ProcessRequest(HttpContext ctx)
    {
        if (ctx.Request.QueryString["asm"] == "true")
            _showAssemblies = true;

        ctx.Response.Write("<hr>");

        foreach (string s in _handlerNames)
        {
            _showHandlers(s);
        }

        ctx.Response.Write("<hr>");
    }

    public void _showHandlers(string handlerName)
    {
        HttpResponse r = HttpContext.Current.Response;
        object key = _getPrivateAppField("Event" + handlerName);
        EventHandlerList ehl = (EventHandlerList)_getPrivateAppField("_events");
        MulticastDelegate md = (MulticastDelegate)ehl[key];
        if (null != md)
        {
            r.Output.WriteLine("<h2>{0}</h2>", handlerName);
            foreach (Delegate d in md.GetInvocationList())
            {
                Type tt = d.Target.GetType();
                string asm = "";
                if (_showAssemblies)
                {
                    asm = string.Format("<font color='red'>[{0}]</font>", tt.Assembly.GetName());
                }
                r.Output.WriteLine("{0}{1}.<font color='blue'>{2}</font><br>", asm, tt, d.Method.Name);
            }
        }
    }
    object _getPrivateAppField(string fieldName)
    {
        return _getPrivateField(typeof(HttpApplication), fieldName, HttpContext.Current.ApplicationInstance);
    }

    object _getPrivateField(Type t, string fieldName, object o)
    {
        return t.GetField(fieldName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic).GetValue(o);
    }

    object _getPrivateField(string fieldName, object o)
    {
        return o.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic).GetValue(o);
    }

    public bool IsReusable { get { return true; } }
}
...