How can I prevent requests from certain domain in web.config? - asp.net-mvc

I want to restrict one domain for my application in web.config. How can I do it? I just found solution for IIS settings, like
<add ipAddress="some_ip_address" />
but I want to restrict a domain, not IP address

There is no direct way to not allow specific domain.You can restrict certain IPs only.
You can always use nsloopkup to map domain to its IP addresses.
<security>
<ipSecurity allowUnlisted="true">
<clear/> <!-- removes all upstream restrictions -->
<add ipAddress="83.116.19.53"/>
</ipSecurity>
</security>

There is no direct setting in the web.config to do this. However you can create a custom collection in the web.config to list your domains and the write a custom requesthandler or a custom actionfilter that would block the specific domain. However this can very easily be spoofed or bypassed. Here is an example:
Your configsection class:
public class DisallowedDomainsSection : ConfigurationSection
{
// Create a "remoteOnly" attribute.
[ConfigurationProperty("remoteOnly", DefaultValue = "false", IsRequired = false)]
public Boolean RemoteOnly
{
get
{
return (Boolean)this["remoteOnly"];
}
set
{
this["remoteOnly"] = value;
}
}
// Create a "domain" element.
[ConfigurationProperty("domainName")]
public DomainElement Domain
{
get
{
return (DomainElement)this["domainName"]; }
set
{ this["domainName"] = value; }
}
}
Then you declare your config section in the configSections node:
<configSections>
<sectionGroup name="disAllowDomainsGroup">
<section
name="disallowDomains"
type="your.class.definition"
allowLocation="true"
allowDefinition="Everywhere"
/>
</sectionGroup>
</configSections>
Then you declare the action section:
<configuration>
<!-- Configuration section settings area. -->
<disallowDomainsGroup>
<disallowDomain remoteOnly="true">
<domainName="www.google.com" />
</dissallowDomain>
</disallowDomainsGroup>
</configuration>
Finally you create a ActionFilterAttribute to get the list of disallowed domains and redirect/restrict the user if they are originating from the domain.
You can access the newly created webconfig section like this:
DomainsDisallowedSection config =
(DomainsDisallowedSection)System.Configuration.ConfigurationManager.GetSection(
"disallowDomainsGroup/disallowDomains");
and then iterate through your disallowed domains and use
HttpContext.Current.Request.Url.Host
to match the disallowed domain with the request domain. But as previously stated this can be bypassed quite easily by someone who knows how.

In IIS Manager:
Select the desired site.
In the Home pane, open IP Address and Domain Restrictions.
In the Actions pane, launch Edit Feature Settings...
Check the box for Enable domain name restrictions
Click [OK] to exit.
You can now add domain names the same way you add IP addresses.
Note: This cannot be done through web.config. The settings are stored in ApplicationHost.config. You will have to get access to IIS Manager to enable IP and Domain Security though. There is no way around this.
<ipSecurity enableReverseDns="true">
<add ipAddress="192.168.0.1" allowed="false" />
<add domainName="google.com" allowed="false" />
</ipSecurity>

Related

How to override Elmah applicationname set in Web.config

We have a multi-tenanted MVC app, meaning that exactly the same app is published to multiple IIS virtual directories / applications, and then the app its self works out who it is, and skins its self (css) accordingly.
This is all very well, but anything logged by ELMAH in our elmah database gets logged under the same applicationName, as this is pulled out of Web.Config elmah section below where everything would be logged as "MyappName" :
<configuration>
[...]
<elmah>
<security allowRemoteAccess="false" />
<errorLog
type="Elmah.SqlErrorLog, Elmah"
connectionStringName="elmah"
applicationName="MyappName" />
</elmah>
</configuration>
The question is therefore how to override the applicationName setting from web.config with something specific so we can distinguish errors for a given tenant web site.
As this is configurable within the web.config, ELMAH are already providing you with a way to specify the application name when the application is deployed to different locations - it's just a case of making use of it.
This would generally be something that you would manipulate as part of your deployment steps. If you are doing it manually then it's going to be a pain, but it could be easily manipulated by using a web.config transform.
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<elmah>
<errorLog applicationName="MyappName" xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
</elmah>
</configuration>
I wonder if the following might work, if you put the following into your Global.asax:
var service = ServiceCenter.Current;
ServiceCenter.Current = context =>
{
var connectionString = "YOUR CONNECTION STRING";
var container = new ServiceContainer(service(context));
var log = new SqlErrorLog(connectionString) { ApplicationName = "APP NAME HERE" };
container.AddService(typeof(ErrorLog), log);
return container;
};

Sitecore adding port numbers to all URLs

Wondering if anyone has seen this behavior before. My instance of Sitecore 6.6 appends the port number to all the URLs it generates for my site. So for example, a link to the home page should be "https://example.org", but instead it's generated as "https://example.org:443". Everything functions fine with the port numbers, but it's muddling some stuff we're trying to do with SEO and canonicalization. Does anyone know if there's a setting or setup to not produce the port numbers? (I'm sure I could rewrite the URLs by catching them at the appropriate point in the pipeline, but I'm hoping for a simpler way before I jump to that.)
The Sitecore LinkManager is indeed not so clever. We also experienced this issue with a mix of proxy servers and load balancers. To remove the ports, we have created a custom LinkProvider which removes the port if needed (untested code sample):
public class LinkProvider : Sitecore.Links.LinkProvider
{
public override string GetItemUrl(Item item, UrlOptions options)
{
var url = base.GetItemUrl(item, options);
if (url.StartsWith("https://"))
{
url = url.Replace(":443", string.Empty);
}
return url;
}
}
And configure the new LinkProvider:
<configuration xmlns:set="http://www.sitecore.net/xmlconfig/set/">
<sitecore>
<linkManager defaultProvider="sitecore">
<providers>
<add name="sitecore" set:type="Website.LinkProvider, Website" />
</providers>
</linkManager>
</sitecore>
</configuration>
This is caused by having the 'scheme' property in the configuration/sitecore/sites/site element of the web.config (or patched config) being set to 'http' explicitly, but making requests over SSL. Removing this, or setting it to 'https' resolves the issue.
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<sites>
<site patch:before="*[#name='website']"
name="my_website"
hostName="my_website.com"
scheme="http"
...
</sites>
</sitecore>
</configuration>
It's a known bug:
https://kb.sitecore.net/articles/913585
There is a patch for releases below 9.1 available here:
https://github.com/SitecoreSupport/Sitecore.Support.93141/releases
I agree with Jan's findings: setting externalPort on the site node in the configuration convinces Sitecore to exclude the port in a generated URL. I did a full write-up on my blog, including using the result for canonical URL tags.
http://findgnosis.com/2017/06/26/hiding-port-urls-produced-sitecores-linkmanager/
LinkManager:
You can cheat the LinkManager by adding port="443" externalPort="80" to your site-definition in <sites>. Don't know if this will cause other issues though.
<configuration>
<sitecore>
<sites>
<site name="website" port="443" externalPort="80" />
</sites>
</sitecore>
</configuration>
MediaManager:
If you know the url, set the Media.MediaLinkServerUrl-setting, to prevent Sitecore from creating the wrong url. Otherwise...
class SslFriendlyMediaProvider : MediaProvider
{
public override string GetMediaUrl(MediaItem item, MediaUrlOptions options)
{
var url = base.GetMediaUrl(item, options);
if(options.AlwaysIncludeServerUrl)
// https://example.com:443/a b?c=123 --> https://example.com/a%20b?c=123
return new Uri(url).AbsoluteUri;
return url;
}
}
Config:
<configuration xmlns:set="http://www.sitecore.net/xmlconfig/set/">
<sitecore>
<mediaLibrary>
<mediaProvider set:type="SslFriendlyMediaProvider, Assembly" />
</mediaLibrary>
</sitecore>
</configuration>

MVC .Net can't get it to stop trying to recreate tables

I had migrations enabled - however, now I'm moving to the live server, it appears migrations are still trying to update the database, as I get the error:
CREATE TABLE permission denied in database 'secn'.
I have this in a context file in my models folder:
namespace lhts2.Models
{
public class DefaultConnection : DbContext
{
public DefaultConnection() : base("name=DefaultConnection")
{
Database.SetInitializer<DefaultConnection>(null);
}
}
}
...and in my web.config file, my connection string is:
<add name="DefaultConnection" connectionString="Data Source=[servername];
Initial Catalog=secn; Integrated Security=True;" providerName="System.Data.SqlClient" />
I have deleted the Migrations folder too, and republished - but still I get the error above.
I also have this in my web.config file:
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
Do I need to set the SetInitializer in some other place, other than in the context file in my models folder?
Thanks for any advice,
Mark
From here:
...the initializer should have been set in the static constructor of your context. The static constructor is called before any constructors and is executed once. This is what we want. The reason is that in some of your application, you may initialize more than once the context. You do not want to execute all the process to check if the database if ready to be changed or not.
So, you should change your class to have a static constructor that is only called one time.
namespace lhts2.Models
{
public class DefaultConnection : DbContext
{
static DefaultConnection()
{
Database.SetInitializer<DefaultConnection>(null);
}
public DefaultConnection() : base("name=DefaultConnection")
{
}
}
}
I had the same issue. Setting the IIS user to a "sysad" level user allowed the application to work normally. However that is not a secure method of solving the problem.
Further research revealed that the "migrations" table (named dbo.__MigrationHistory) was the culprit. I had given the IIS user access (Select, Update, Delete, Insert, and References) to all the "application" tables, but not the "migrations" table. Consequently when the application runs and attempts to determine if a migration is necessary, the access fails because of the lack of access rights for that user and the application thinks it needs to create the database and tables - which this user clearly should not have rights to do.
By providing normal access rights to the __MigrationHistory table (Select, Update, Delete, Insert, and References) the IIS user was now able to determine that no migration was necessary and therefore did not attempt to conduct a migration.
Example of Permission Settings Here

Specifying Roles in web.config of an asp.net MVC application

I am creating an MVC application with forms auth. I am authenticating against active directory and so have created a custom RoleProvider. My application is only concerned with a small set of roles which up until now I have been defining in the appSettings section of my web.config:
<appSettings>
<add key="DirectorRole" value="Domain\Directors" />
<add key="ManagementRole" value="Domain\Managers" />
...
</appSettings>
However I have run into a couple of problems with this approach:
I cannot reference these setting in my contoller data annotations: [Authorize(Roles = ConfigurationManager.AppSettings["DirectorRole"])] as it wont compile so I have to specify the name of the group again: [Authorize(Roles = "Domain\\Directors")].
In my web.config, I would like to specify the groupsToUse for my role provider and just reference a pre-existing list, rather than maintain two seperate lists of the same set of roles.
It seems that there must be a better/reusable way to define the roles in the web.config, can someone point me in the right direction please?
I would prefer using a custom authorize attribute. Like this one.
public class MyAuthorizeAttribute : AuthorizeAttribute {
public MyAuthorizeAttribute(params string[] roleKeys) {
List<string> roles = new List<string>(roleKeys.Length);
//foreach(var roleKey in roleKeys) {
//roles.Add(ConfigurationManager.AppSettings["DirectorRole"]);
//}
var allRoles = (NameValueCollection)ConfigurationManager.GetSection("roles");
foreach(var roleKey in roleKeys) {
roles.Add(allRoles[roleKey]);
}
this.Roles = string.Join(",", roles);
}
}
In your controller, use:
[MyAuthorize("DirectorRole")]
In your web.config
<configSections>
<section
name="roles"
type="System.Configuration.NameValueFileSectionHandler,System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</configSections>
<roles>
<add key="DirectorRole" value="Domain\Directors" />
<add key="ManagementRole" value="Domain\Managers" />
</roles>
I hope this will solve your first problem just fine. And twiking a little will solve the second one too.
Please have a look at this excellent example, in which author talks about the problem you are facing.
http://www.ryanmwright.com/2010/04/25/dynamic-controlleraction-authorization-in-asp-net-mvc/

Disable client side caching

I've been searching for info on how to disable client side caching on project level.
I know I can add the following before an action method:
[System.Web.Mvc.OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
I also read something about making profiles for caching, but that would also mean refering to them in several places. I would like a single setting in web.config, or maybe in IIS?
The project I'm working on contains a lot of partial views
Thank you in advance for any advice in this matter.
You can disable browser caching via Web.Config:
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Cache-Control" value="no-cache, no-store" />
<add name="Pragma" value="no-cache" />
<add name="Expires" value="-1" />
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>
Source: http://blog.jamesjones.name/2009/11/how-to-disable-browser-caching-in.html
Edit: added no-store to Cache-Control for Chrome ( http://code.google.com/p/chromium/issues/detail?id=28035 )
You can set this at the project level or at the subdirectory level to control browser caching as desired. For example, in a primarily data-driven/dynamic site, I may set these headers at the project level, but in a /static directory (which contains my .js, .css, images), add another web.config which includes the appropriate </clear> directive, and perhaps set a far-future-expires header instead.
You could make BaseController and set your cache profile to it.
Then make all of your controllers to inherit from this BaseController.
Update:
Here is what I've :
// Here is my custom OutputCaheAttribute to prevent cache at all.
//Whatever you may put anything you want.
//Of course i don't use it here but i put it to show you how it's going.
[NoCache]
public class BaseController : Controller
{
protected override ViewResult View(string viewName, string masterName, object model)
{
// I do some stuffs here to change MasterPage depending on current culture.
// Don't care about it i just wanna show you why BaseController is good idea.
}
}
Then ALL my controllers inherits from this BaseController instead of normal Controller.
Hope this was helpful ;)
Expanding on #Tom's answer, for per file or per directory based cache busting :
<configuration>
<!-- disable cache for every file in this directory -->
<location path="dist">
<system.webServer>
<staticContent>
<clientCache cacheControlMode="DisableCache" />
</staticContent>
<httpProtocol>
<customHeaders>
<add name="Cache-Control" value="no-cache, no-store, must-revalidate, pre-check=0, post-check=0, max-age=0, s-maxage=0" />
<add name="Pragma" value="no-cache" />
<add name="Expires" value="-1" />
</customHeaders>
</httpProtocol>
</system.webServer>
</location>
</configuration>
You can define cache profiles in web.config, however, using cache profiles doesn't seem to work with OutputCache attribute in mvc 3. Read this question: Caching ChildActions using cache profiles won't work?
The OutputCache attribute is used for server side output action output caching. To turn it off, you just don't apply the attribute to the action/controller. If you want to disable client side, then that is taken care of by adding a header informing the browser not to cache the result.
If you need to cache files in a subfolder for 1 day (24 hours), you can add a separate web.config to these sub folders (requires clearing client cache the first time).
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="00:24:00" />
</staticContent>
</system.webServer>
</configuration>
Try this
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]

Resources