将 Auth 和 Session Cookie 限制到 ASP.NET MVC 5 中的子域

Restrict Auth & Session Cookies to a Subdomain in ASP.NET MVC5

我有一个包含多个客户端的多租户应用程序,它们按子域区分:

client1.mydomain.com
client2.mydomain.com
etc

我正在使用表单身份验证,客户端上的 ASP.NET 身份验证和会话 cookie 是为子域设置的,例如client1.mydomain.com。这意味着如果我浏览到 client2.mydomain.com 然后我没有登录并且浏览器不会 post client1 cookies。这是应该的。

然而,我们的安全测试发现,您可以从 client1 获取 cookie 值并使用这些值为 client2 创建 cookie(我们已在 firebug 中完成此操作)。 ASP.NET 接受这些 cookie 并认为您在 client2 上获得授权。

如何配置 ASP.NET 以免发生这种情况?

web.config 中的表单元素允许您设置域,但我不能使用它,因为我有一个多租户应用程序。我用

设置 cookie
 FormsAuthentication.SetAuthCookie(userName, false);

但我不明白为什么要将此限制为子域。

您应该将域名添加到cookie的用户数据中。为此,您必须切换到另一个 cookie api:

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
   ... other parameters ..., domain );

HttpCookie cookie = new HttpCookie( FormsAuthentication.FormsCookieName );

cookie.Value = FormsAuthentication.Encrypt( ticket );

Response.SetCookie( cookie );

然后,在您的全局应用程序中 class 有一个事件处理程序,它会在 为请求建立身份后 触发。在处理程序中,验证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。