主域名网站+子域名上的安全MVC网络应用程序

时间:2014-03-16 00:43:06

标签: asp.net-mvc iis ssl asp.net-mvc-routing subdomain

问题

我试图实现以下目标:

(注意:此域/子域仅用于说明目的。)

我已经从我的主机WinHost获得了SSL / TLS证书,并且我只将其应用于子域(secure.somedomain.com),而不是主域(somedomain) .COM)。

当我发布MVC应用程序时,文件实际存储在somedomain.com/secure目录中。

让这一切全部工作已经证明很多比我认为的更难。


到目前为止我尝试了什么

我发现了一些关于如何针对不同目的使用不同子域的问题(例如,每种语言一个子域,每个公司一个子域等),但我的需求更简单 - 我只是想要我的整个MVC应用程序都是从一个子域托管的。

到目前为止,我已尝试过两种基本方法(独立和组合):

  1. 使用IIS管理器设置基本上转换对secure.somedomain.com的请求的URL重写 - > somedomain.com/secure。

  2. 在我的MVC应用程序中编写自定义路由和/或约束,并将它们添加到我的Global.asax.cs文件中的RouteCollection。

  3. 我对方法#1 运气不错。我最终设法提出了一些规则:(1)不干扰主域上的网站,(2)阻止对somedomain / secure的任何请求(因为安全证书对主域没有效果), (3)根据对secure.somedomain.com的请求提供正确的页面。

    此方法的主要失败(至少是孤立的)是不再提供静态内容,未经身份验证的用户请求会导致错误的网址,例如" https://secure.somedomain.dom/secure/somecontroller/someaction/?ReturnUrl=%2fsomecontroller" (注意额外的"安全")。

    对于记录,这是我的URL重写:

    <system.webServer>
        <rewrite>
            <rules>
                <rule name="subdomain" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions>
                        <add input="{HTTP_HOST}" pattern="^(secure.)somedomain.com$" />
                    </conditions>
                    <action type="Rewrite" url="\secure\{R:0}" />
                </rule>
                <rule name="subfolder" stopProcessing="true">
                    <match url=".*" />
                    <conditions>
                        <add input="{URL}" matchType="Pattern" pattern="^(http://|https://)?(www)?[^/]*/secure" ignoreCase="true" negate="false" />
                    </conditions>
                    <action type="CustomResponse" statusCode="403" statusReason="Forbidden: Access is denied." statusDescription="You do not have permission to view this directory or page using the credentials that you supplied." />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
    

    对于方法#2 ,老实说,我不能说我尝试的任何事情都有很大的不同(无论是与URL重写还是单独组合)。

    首先,我尝试编写以下自定义路由,我基本上从https://stackoverflow.com/a/15287579/129164偷走了:

    public class SubdomainRoute : Route
    {
        private const string _subdomain = "secure";
    
        public SubdomainRoute(string url) : base(url, new MvcRouteHandler()) { }
    
        public override RouteData GetRouteData(HttpContextBase httpContext)
        {
            var routeData = base.GetRouteData(httpContext);
            if (routeData == null) return null; // Only look at the subdomain if this route matches in the first place.
    
            // A subdomain specified as a query parameter takes precedence over the hostname.
            var subdomain = httpContext.Request.Params[_subdomain];
            if (subdomain == null)
            {
                var host = httpContext.Request.Headers["Host"];
                var index = host.IndexOf('.');
                if (index >= 0) subdomain = host.Substring(0, index);
            }
            if (subdomain != null) routeData.Values[_subdomain] = subdomain;
            return routeData;
        }
    
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            var subdomainParam = requestContext.HttpContext.Request.Params[_subdomain];
            if (subdomainParam != null) values[_subdomain] = subdomainParam;
            return base.GetVirtualPath(requestContext, values);
        }
    }
    

    我试图在Global.asax.cs中将它连接起来:

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.Add(
            "Default",
            new SubdomainRoute("{controller}/{action}/{id}")
            {
                Defaults = new RouteValueDictionary(
                    new { controller = MVC.Home.Name, action = MVC.Home.ActionNames.Index, id = UrlParameter.Optional }),
                Constraints = new RouteValueDictionary(
                    new { controller = @"[^\.]*" })
            });
    }
    

    (我基本上将routes.MapRoute()替换为routes.Add()。)

    我还尝试按照https://stackoverflow.com/a/15234839/129164的建议创建自定义路由约束而不是自定义路由。我的班级看起来像这样:

    public class SubdomainRouteConstraint : IRouteConstraint
    {
        private readonly string _subdomain;
    
        public SubdomainRouteConstraint(string subdomain)
        {
            _subdomain = subdomain;
        }
    
        public bool Match(
            HttpContextBase httpContext,
            Route route,
            string parameterName,
            RouteValueDictionary values,
            RouteDirection routeDirection)
        {
            return httpContext.Request.Url != null && httpContext.Request.Url.Host.StartsWith(_subdomain);
        }
    }
    

    我将RegisterRoutes方法更新为:

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.MapRoute(
            "Default" /* Route name */,
            "{controller}/{action}/{id}" /* URL with parameters */,
            new { controller = MVC.Home.Name, action = MVC.Home.ActionNames.Index, id = UrlParameter.Optional } /* Parameter defaults */,
            new { controller = @"[^\.]*", subdomain = new SubdomainRouteConstraint("secure") } /* Parameter constraints */);
    }
    

    再次,当我尝试这个时,我没有看到任何区别。

    我遇到的其他一些答案建议编写扩展方法,基本上修改Html.ActionLinkUrl.Content以根据需要修复网址,但我确实对此方法有抵触,因为它会需要进行大量的重构才能搞定(并且鉴于我到目前为止运气不好,我并不相信它会起作用)。


    无论如何,如果你还在我身边,我可以真正使用一些建议来解决如何设置我的安全子域(希望如此),而无需对我的MVC应用程序进行重大改动。

    另外,如果你看到我到目前为止所尝试的解决方案中有任何明显的错误,或者你对我应该尝试的具体修改或组合有一些想法,请告诉我。

2 个答案:

答案 0 :(得分:1)

我可能不完全了解您的设置/要求,但如果您有两个单独的域用于两个具有不同目的的实体,为什么不使用两个网站而不是一个网站。

只需在绑定中设置主机头,并使安全站点的根指向安全文件夹。如果您需要静态站点中的某些静态文件,只需通过虚拟目录将其引入。无需URL重写或路由。

如果您需要将secure文件夹存储在静态网站下但不希望用户在那里看到它,请隐藏它:

<system.webServer>
  <security>
    <requestFiltering>
      <hiddenSegments>
         <add segment="secure" />
      </hiddenSegments>
     </requestFiltering>
   </security>
</system.webServer>

答案 1 :(得分:0)

此处有类似的问题 - somedomain.com和abc.subdomain.com。 (均在ASP.Net 4.0中) somedomain.com中的静态html文件

将一个简单的aspx文件部署到abc.subdomain.com中。 - 工作正常。

将一个简单的mvc3应用程序部署到abc.subdomain.com。 - 不工作显示消息禁止 - 您没有权限访问/在此服务器上。 (错误403)。

没有对global.asax和webconfig进行任何更改。

部署模式 - 发布到本地文件夹和ftp上传。 (添加了所有依赖项)。