I have a website that uses basic ASP.Net forms authentication. In the web.config file we specify specific access rules for individual pages and directories. Everything works great.
However, now I have some new requirements. My domain contains many different sites setup among different subdomains. I have two DNS subdomains that map to this application. One is aaa.mysite.com and the other is www.mysite.com. If a particular web request is received from subdomain aaa.mysite.com for a page protected by FormsAuthentication, before the FormsAuthentication logic is handled (the user would be re-directed to the login page), I want to execute some code first. This code would essentially try to read a cookie from a third sub开发者_StackOverflowdomain, say zzz.mysite.com, and if does not exist, Response.Redirect to a login page in the zzz.mysite.com application.
I tried handling this via a base class that any of my Forms Authentication protected pages could inherit from, and then calling the special code in the Page_PreInit function. However, FormsAuthentication handles the redirect to the Login page even before the PreInit function is called.
Does anyone know a good way to handle this case? If Page_PreInit won't work, where can I put code so that it executes prior to the FormsAuthentication redirect does, but where I also have access to which page it is (and what class it inherits from, so I can see if it inherits from System.Web.UI.Page or if it inherits from my special BasePage).
Any ideas? I think I could use the Globals Application_BeginRequest, but then this would be called for every single request, which doesn't seem like a very good idea.
I can't be the first person who has needed a way to handle an event prior to the FormsAuthentication, so please if you could give me some additional ideas I would be very appreciative!
Thanks!
If the cookie has been written to zzz.example.com
then a site on www.example.com
cannot read it - the way to share cookies across subdomains is to write them to .example.com
.
This can be configured in forms authentication using the domain
attribute on the forms element in the web.config:
<forms [...]
domain=".example.com">
Note the leading period in the domain names.
Edit to respond to comment
You should probably be hooking into the PostAuthenticateRequest event - this is fired after the users identity (or lack of) is established, and you could register a custom HttpModule to receive this event.
Edit to show workings
Ok, I've just tested the following setup:
A web application project, with the following directory structure:
/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
So, the root web.config sets up Forms authentication, using a standard ASP.NET membership provider, and sets /Login.aspx
as the login page. I have also registered a custom HttpModule in there:
<httpModules>
<add name="CheckingAuthenticate"
type="TempWebApp.Classes.CheckingAuthenticate"/>
[...]
</httpModules>
The web.config in /Restricted/
denies access to anonymous users (this could equally be done in a <location>
element in the root):
<configuration>
<system.web>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</configuration>
I then have the following code in my http module:
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.
}
}
}
}
This will fire after the user has been authenticated, but before ASP.NET attempts to authorize the user, so you get a chance to check the access yourself and redirect instead. I've been able to hit breakpoints on that quite happily. I didn't get to see the AuthorizeRequest or PostAuthorizeRequest events if the user didn't have access to those pages.
I think you should use the AuthenticateRequest event. See the lifecycle. Don't worry about it happening on every request, a lot of stuff does that.
精彩评论