2010-03-08 3 views
2

У меня есть веб-сайт, который использует базовую аутентификацию форм ASP.Net. В файле web.config мы указываем конкретные правила доступа для отдельных страниц и каталогов. Все отлично работает.Как обработать событие страницы перед перенаправлением подлинности с помощью форм?

Однако, теперь у меня есть некоторые новые требования. Мой домен содержит множество различных сайтов, устанавливаемых между разными субдоменами. У меня есть два поддомена DNS, которые сопоставляются с этим приложением. Один из них - aaa.mysite.com, а другой - www.mysite.com. Если конкретный веб-запрос получен из субдомена aaa.mysite.com для страницы, защищенной FormsAuthentication, перед обработкой логики FormsAuthentication (пользователь будет перенаправлен на страницу входа в систему), я хочу сначала выполнить код. Этот код по существу попытается прочитать куки из третьего субдомена, скажем, zzz.mysite.com, а если не существует, Response.Redirect на страницу входа в приложение zzz.mysite.com.

Я попытался обработать это с помощью базового класса, который могла бы наследовать любая из защищенных страниц с проверкой подлинности с помощью форм, а затем вызов специального кода в функции Page_PreInit. Однако FormsAuthentication обрабатывает перенаправление на страницу входа еще до вызова функции PreInit.

Кто-нибудь знает хороший способ справиться с этим делом? Если Page_PreInit не будет работать, где я могу поместить код так, чтобы он выполнялся до перенаправления FormsAuthentication, но где у меня также есть доступ к какой странице он (и какой класс он наследует, поэтому я могу видеть, наследует ли он от System.Web.UI.Page или если он наследуется от моего специального BasePage).

Любые идеи? Я думаю, что я мог бы использовать Globals Application_BeginRequest, но тогда это будет вызвано для каждого отдельного запроса, что не кажется очень хорошей идеей.

Я не могу быть первым, кому нужен способ справиться с событием до FormsAuthentication, поэтому, пожалуйста, если бы вы могли дать мне дополнительные идеи, я был бы очень благодарен!

Спасибо!

ответ

1

Если файл cookie был написан на zzz.example.com, то сайт на www.example.com не может его прочитать - способ обмена куками по субдоменам - записать их в .example.com.

Это может быть сконфигурирован в формах проверки подлинности с помощью атрибута на forms elementdomain в web.config:

<forms [...] 
    domain=".example.com"> 

Примечания ведущего периода в доменных именах.

Редактировать, чтобы ответить на комментарий

Вы, вероятно, следует закреплять в PostAuthenticateRequest event - это срабатывает после того, как личность пользователей (или отсутствие) установлено, и вы можете зарегистрировать custom HttpModule получить это событие.

Редактировать, чтобы показать выработках

Хорошо, я только что проверил следующие настройки:

проект веб-приложения, со следующей структурой каталогов:

/Default.aspx     -- Simple aspx page. 
/Login.aspx      -- Simple aspx page, with a Login control. 
/web.config      -- Main application config. 
/Classes/CheckingAuthenticate.cs -- HttpModule, configured in root. 
/Restricted/Default.aspx   -- Simple asp page. 
/Restricted/web.config   -- Config file for authorization 

Таким образом, root web.config устанавливает аутентификацию форм, используя стандартный поставщик членства в ASP.NET, и устанавливает /Login.aspx в качестве страницы входа. Я также зарегистрировал собственный HttpModule в там:

<httpModules> 
    <add name="CheckingAuthenticate" 
     type="TempWebApp.Classes.CheckingAuthenticate"/> 
    [...] 
</httpModules> 

web.config, в /Restricted/ запрещает доступ анонимных пользователей (это может также осуществляться в <location> элемента в корне):

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

Я тогда следующий код в моем HTTP модуль:

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

namespace TempWebApp.Classes { 
    public class CheckingAuthenticate : IHttpModule { 

    public void Dispose() { 
     //clean-up code here. 
    } 

    public void Init(HttpApplication context) { 
     context.PostAuthenticateRequest += OnPostAuthenticate; 
    } 

    public void OnPostAuthenticate(object sender, EventArgs e) { 
     var app = sender as HttpApplication; 

     if (!UrlAuthorizationModule.CheckUrlAccessForPrincipal(app.Request.Path, 
                  app.User, 
                  "GET")){ 
     //Code here to read cookies, redirect user etc. 
     } 
    } 
    } 
} 

Это будет срабатывать после того, как пользователь был аутентифицирован, но до попыток ASP.NET для авторизации пользователя, так что вы получите возможность проверить доступ самостоятельно и перенаправить. Я очень счастлив ударить по точкам останова. Я не смог увидеть события AuthorizeRequest или PostAuthorizeRequest, если у пользователя не было доступа к этим страницам.

+0

Да, это правда, cookie написан на .example.com, так что все субдомены могут получить к нему доступ. Вопрос остается, если файл cookie еще не существует, как я могу ответить Response.Redirect их в другой домен до перенаправления проверки подлинности форм? – kazzamalla

+0

Я могу определенно написать код в моем файле Global.asax.cs для этого события, но не тот огонь после того, как пользователь был аутентифицирован? Я хочу сделать свое перенаправление до того, как пользователь будет перенаправлен формами «Аутентификация» на страницу входа в систему и попросил войти в систему. Однако, как и в моем комментарии к Хэнку, мне нужен способ проверить, защищена ли страница, которую пользователь пытается получить, с помощью проверки подлинности форм. Есть идеи? – kazzamalla

1

Я думаю, вы должны использовать событие AuthenticateRequest. См. lifecycle. Не беспокойтесь о том, что это происходит по каждому запросу, многие вещи делают это.

+0

Если я использовал этот метод, какой метод я вызываю, чтобы проверить, нужна ли текущая страница для доступа к подлинности на основе правил в web.config? – kazzamalla

+0

Я нашел UrlAuthorizationModule.CheckUrlAccessForPrincipal, но для этого метода требуется действительный объект IPrincipal, и на этом этапе жизненного цикла HttpContext.Current.User имеет значение null. Я не знаю пользователя на этом этапе, потому что я хочу перенаправить до выяснения. Есть идеи? – kazzamalla

+0

Проверьте связанную страницу. Следующее событие - PostAuthenticateRequest. Вероятно, вы также можете использовать AuthorizeRequest. –