我有一个多租户的应用程序,有几个客户端,以子域名区分:
client1.mydomain.com
client2.mydomain.com
etc
我正在使用表单身份验证和ASP.NET Auth&客户端上的会话cookie是为子域设置的,例如, client1.mydomain.com。这意味着如果我浏览到client2.mydomain.com,那么我没有登录,浏览器也没有发布client1 cookie。这是应该的。
然而,我们的安全测试已经提到的一点是,您可以从client1获取cookie值并使用这些值为client2创建cookie(我们已在firebug中完成此操作)。 ASP.NET接受这些cookie并认为您已在client2上获得授权。
如何配置ASP.NET以便不会发生这种情况?
web.config中的表单元素允许您设置域名,但我无法使用此作为我的多租户应用程序。我用
设置了cookie FormsAuthentication.SetAuthCookie(userName, false);
但我不明白为什么要将此限制为子域名。
答案 0 :(得分:2)
您应该将域名添加到cookie的用户数据中。要做到这一点,你必须切换到另一个cookie api:
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
... other parameters ..., domain );
HttpCookie cookie = new HttpCookie( FormsAuthentication.FormsCookieName );
cookie.Value = FormsAuthentication.Encrypt( ticket );
Response.SetCookie( cookie );
然后,在您的全局应用程序类中有一个事件处理程序,在为请求建立标识后触发。在处理程序中,验证cookie中的域名是否等于当前请求的域:
public void Application_PostAuthorizeRequest( object sender, EventArgs e )
{
HttpApplication app = sender as HttpApplication;
HttpContext ctx = app.Context;
if ( ctx.User.Identity.IsAuthenticated )
{
// current domain
string currentDomain = ctx.Request.Url.... // get the domain
// domain from cookie
FormsIdentity id = (FormsIdentity)ctx.User.Identity;
FormsAuthenticationTicket ticket = id.Ticket;
string cookieDomain = ticket.UserData;
if ( currentDomain != cookieDomain )
throw new Exception( "break the execution of the current request" );
...
此检查将验证cookie是否针对当前域发布,或者是否有人尝试在不同域之间重用cookie。