How can I host multiple websites in IIS 7 and use the same MVC application for all them? - asp.net-mvc-4

How can I host multiple websites in IIS 7 and use the same MVC application for all them such that each website:
Has it's own root directory so user's can upload their own files (html, css, javascript) without seeing other websites'content
Uses the same MVC application - so updates to the application affect all sites
Users cannot affect the MVC application in any way (preferably it will be hidden from them)
Thanks!

Create a directory where you deploy the MVC files, named "AppFoo". Note that the configuration file web.config will be shared between all of the sites, you'll have to load per-site configuration at on-demand runtime by looking at the Host HTTP header or other binding information.
Create each website in IIS and get it to use the the application directory you created. Ideally each website runs under its own application pool with its own user-account, all of the user-accounts will have access to AppFoo directory.
Create a new directory somewhere, e.g. under C:\Inetpub\sites\ named WebsiteA, WebsiteB, etc. Each folder re-sets the NTFS permission ACLs that only allows each website's application pool user access. Inside these create folders called "Content", "Views" and "Logs"
For each website in IIS (I assume you're using the root) set up a Virtual Directory called "Content" and "Views" (which is how I assume you have set-up your MVC applications), map these to subdirectories of the folders you created in Step 3.
For each website, go to the Logging page and set the log-path to the Logs directory you created for the site in step 3.
Note that this plan is based on the assumption that MVC evaluates IIS virtual directories in its VirtualPathProvider. If not then you'll have to roll your own VirtualPathProvider to load per-website content, again, on a per-hostname basis.

If you are running one code base, then setup one site that uses domain routing or a global filter to capture the domain, save it and use it as a key for folders, etc...
public class DomainFilterAttribute : ActionFilterAttribute
{
private SiteDomainRepository _siteDomainRepository = new SiteDomainRepository();
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var viewBag = filterContext.Controller.ViewBag;
var host = HttpContext.Current.Request.IsLocal ? "www.testdomain.com" : HttpContext.Current.Request.Url.Host;
var domain = hostSplit[1];
var siteDomain = _siteDomainRepository.GetByRowKey(domain);
viewBag.DomainName = host.ToLower();
viewBag.Domain = siteDomain.RowKey;
viewBag.Class = siteDomain.Key;
viewBag.TrackingCode = siteDomain.TrackingCode;
}
}

Related

How to protect static pages from being served to unauthenticated users in ASP.NET Core 3.x?

I have an ASP.NET 3.1 web app. I also have a web help documentation system created from the Help & Manual documentation system. These help files include html, JavaScript, image files and possible some videos and PDF files. The web help system is a project created outside of Visual Studio. Normally, I'd use a subdomain but I figure I can deploy it to a folder within the main web app for the purposes of taking advantage of ASP.NET Identity which I'm using for authentication and authorization.
I need to protect all of these assets from unauthenticated users as there is proprietary data but I'm unsure how this can be done. Hoping for a simple and elegant solution.
I think you can get these files by writing an Action, and then adding Attribute to the Action. Here is an example of mine. I have a json file under wwwroot, and I want to have users with the role of "Admin" To access it.Here is my action
[Authorize(Roles = "Admin")]
public IActionResult GetFiles()
{
var file = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "json.json");
return PhysicalFile(file, "application/octet-stream");
}
About PhysicalFile method, you can check this link
https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.controllerbase.physicalfile?view=aspnetcore-3.1

Let's Encrypt with ASP.Net Core and Azure App Service

I have a Runbook in Azure that uses AcmeSharp to generate Let's Encrypt certificates for a website running in Azure App Services. I have used it many times successfully on many ASP.Net sites. Apparently I've never tried it on an ASP.Net Core (2.2) site until now.
I'm pretty sure I was running into the problem described in this blog post - https://ronaldwildenberg.com/letsencrypt-for-asp-net-core-on-azure. Basically, the script publishes a static file to /.wellknown/acme-challenge/randomstring/index.html in my site and then Let's Encrypt tries to verify that file. I'm getting a 404 when trying to hit this URL even though I can see it in the file system in Kudu.
I felt like this was a static file issue in ASP.Net Core and when I found the blog post referred to above - I thought that was going to be the answer. I changed my code as prescribed in the article, but I'm still getting the 404.
Slightly different than the article, instead of files with long random strings of characters like in the article screenshot, my script generates a string like that but creates a folder with that name. Inside each folder is one file (named index.html) that contains the validation info Let's Encrypt is looking for. You can see this at http://www.technicality.online/.well-known/acme-challenge/
You can see the folders are browsable and if you click one, you can see the link to index.html. The problem is - if you click index.html, you get a 404. I've put this in my Startup.Configure:
var rootPath = Path.GetFullPath(".");
var acmeChallengePath =
Path.Combine(rootPath, #".well-known\acme-challenge");
app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
FileProvider = new PhysicalFileProvider(acmeChallengePath),
RequestPath = new PathString("/.well-known/acme-challenge"),
});
app.UseStaticFiles(new StaticFileOptions
{
ServeUnknownFileTypes = true
});
(I don't think I need the ServeUnknownFileTypes since my file is index.html, as opposed to the long random string in the blog post, but I don't think this should hurt anything either.)
I thought maybe the issue was that the file didn't contain valid html (just a string of characters), but I put another file that did contain valid html and I get a 404 when clicking that one as well.
Is there some other ASP.Net Core (or Azure App Service) detail I'm missing to make the application serve up the index.html files?
I figured this out and am posting the answer to hopefully keep someone else from making the same mistake I did. The issue wasn't at all what I thought it was, but rather - there are two "wwwroot" folders in an ASP.Net Core Azure App Service hosting environment and I wasn't paying close enough attention.
The file system path where Azure hosts your application is D:\home\site\wwwroot. In a "classic" ASP.Net scenario, your static files go in that folder. In an ASP.Net Core scenario, another wwwroot folder is created underneath that one. My script (written for ASP.Net) was creating the ".well-known\acme-challenge" folder beneath the first one. The standard app.UseStaticFiles() doesn't help with those.
Basically, I had:
-home
--site
---wwwroot (hosting root)
----wwwroot (ASP.Net core static files folder)
----.well-known (this was a sibling of the 2nd wwwroot and needed to be a child)
I needed to change my script to put my static files under the 2nd wwwroot so that the app.UseStaticFiles() would serve those files.

How is configuration data protected in ASP .NET 5?

Rather than requiring Web.config, ASP .NET 5 provides a number of options to provide configuration data. Info on this can be found at:
Introducing ASP .NET 5 by Scott Guthrie
How can we store configuration data in new asp.net vnext? (StackOverflow)
ASP.NET vNext Moving Parts: IConfiguration by Louis DeJardin
There's an interesting question in the comments section of ScottGu's article:
The config.json file in the example, how is that protected by the webserver/http server? web.config is protected by IIS, but if any file can be used (which is great), it also comes with the burden that the webserver shouldn't serve the file out if one requests it in a URL. Or are there prefab names to choose from?
Can anyone answer this?
In previous versions of ASP.NET root of the project was also a root for the website. Some mechanisms were created to prevent access to files which should not be accessible to the outside world (like a whitelist of mime types, RequestFilteringModule).
This changed in ASP.NET 5 as a website root is no longer a project root.
Website root folder is a subfolder in your project directory (named wwwroot by default, but can be changed in project.json).
This means that everything outside a website root folder is not accessible to the outside world.
config.json file is outside of wwwroot so it won't be ever handled by any requests.

Protect a directory with regular Laravel Auth

I have a secondary application that drops new folders into my Laravel application on a daily basis. The contents of the folder need to be publicly accessible because they're flash files with a number of assets placed in each day's folder, alongside static .html pages, .jpgs, and .swfs. These links are part of the secondary application's vendor-coded framework.
Moving the files from a non-web accessible folder using php doesn't seem like a good option. I've tried using readfile() and considered .htaccess, but I don't want a secondary login for my users.
Only users who have logins with my Laravel application should have access to these files. Is there some way I can protect access to any request inside this folder with Laravel's Auth system, not basic auth? With the understanding that the page requests inside that folder vary?
From extensive searching, I've found that Laravel cannot handle the protection of public folders with static assets. This is a web server configuration issue.
One solution would be to set a cookie that gets read by the web server and bounces the user if the cookie value does not match a predetermined value. But Laravel encrypts cookies and disposes of cookies not encrypted on each load. So that solution would only work if you use App::filter to process the cookie using php setcookie().

How to remove the context path when viewing authenticated content

I'm working on a grails application that sits on a server with another root.war application. Currently we use apache redirects to hide the context path (name of our grails application) as we already have a root.war and we don't want it to show on all our urls. This works for our public content. However, now that we've added some authenticated content with spring security core plugin it always redirects to include the context path. Hence, the url /authcontent/page.gsp is getting redirected to /appname/authcontent/page.gsp. Some folks have mentioned you can remove the context path by creating a separate virtual host in tomcat, but I was wondering if there's a way to override the mechanism that Spring Security uses to do the redirect in the filter chain. Perhaps overriding the RequestCacheAwareFilter? but I believe that filter only is used after the initial authentication. I've read through the spring security documentation but it doesn't talk as much about redirecting requests as much as the whole authentication and authorization process so I'm wondering if this is in the plugin itself. Any thoughts would be helpful.
You can remove the app context in the Config.groovy file:
environments {
development {
grails.logging.jul.usebridge = true
grails.serverURL = "http://localhost:8080"
grails.app.context = "/"
}
production {
grails.logging.jul.usebridge = false
grails.serverURL = "http://yourwebsite.com"
grails.app.context = "/"
}
}
Hope that helps.
There's number of ways of doing this. Two I tried were overriding the requestCache bean (but then you also had to override the DefaultSavedRequest) and overriding the redirectStategy bean which is what I'm using as it was simpler.