Conditional https redirect on IIS 7 - asp.net

I have the following rule on the site to redirect http to https. We just found out though that our app got submitted with just an http for the api. Until we can get this updated I need the site to ignore calls to the /api folder and only redirect everything else. I'm sure there's a way to say something like if URL does not contain /api/ then redirect.
<rewrite>
<rules>
<rule name="HTTP to HTTPS redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
</rule>
</rules>
</rewrite>

Add an entry similar to <add input="{R:0}" pattern="/api(/|$)(.*)" negate="true" /> so that the whole file is:
<rewrite>
<rules>
<rule name="HTTP to HTTPS redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{R:0}" pattern="/api(/|$)(.*)" negate="true" />
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
</rule>
</rules>
</rewrite>
Example URL: http://site.com/api/function
So, if the URL after the site matches any of the following it will stop processing (and thus not push the user to https)
/api
/api/anything
Any https URL
We run into the same kind of thing with a large application run in IIS behind a reverse proxy. The URL rewrite addon for IIS (that you appear to be using) is a bit of a pain, but it does the job really well and tolerates the MVC framework.
As you mentioned, simply putting a rewrite block in an API directory won't work because with MVC there are no directories. You would think MS would have a better solution for this -- but they don't. It makes things all the more challenging.

If you place a separate Web.config file in the /api application or directory you can override whatever rules apply for the site as a whole.
Check out Tip #1 in this article, and if you have the time read them all:
http://weblogs.asp.net/jgalloway/archive/2012/01/17/10-things-asp-net-developers-should-know-about-web-config-inheritance-and-overrides.aspx
John Galloway's blog is a fantastic resource for all things IIS and ASP.NET.

Related

HTTP to HTTPS not working for my asp.net website

I tried almost all upvoted suggestions related to web.config changes for http to https redirection. Best way in asp.net to force https for an entire site?
But it's not working for me for my ASP.net site. I use GoDaddy shared hosting and have multiple sites in my account. I have ssl enabled only for one website and have to add it to filter so that other sites in the same account are not redirected to https. Here's my web.config:
<rewrite>
<rules>
<rule name="HTTP to HTTPS redirect" stopProcessing="true" enabled="true">
<match url="singledomain.*" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" redirectType="Permanent" url="https://{HTTP_HOST}/{R:1}" />
</rule>
</rules>
</rewrite>
I can access the site currently by both http and https. But it never redirects from http to https. Is the match condition correct, and if it is, what else could be the problem?
Found the solution here: https://stackoverflow.com/a/17066105/2535756
Posting the code here which worked:
<rewrite>
<rules>
<rule name="HTTP to HTTPS" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" pattern="(singledomain.com.*)" />
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" redirectType="Permanent" url="https://{HTTP_HOST}/{R:1}" />
</rule>
</rules>
</rewrite>
With GoDaddy, in my experience, there is a setting in the Plesk app that actually will force a re-direct from HTTP to HTTPS.You can find this under your IIS settings under the Directory Security Settings and checking the Require SSL/TSL box. This forces the users' browser to use HTTPS instead of HTTP.

IIS auto redirect http to https for select applications in a website

I have setup a website in IIS and this website has two applications (as shown in the snapshot below).
I have to enable https on the applications. I have installed the SSL certificate and setup the applications to use https instead of http. Now I want to implement autoredirect from http to https, ONLY for the test application (PersonalCornerTest).
I am using UrlRewrite using the below links as reference,
https://www.sslshopper.com/iis7-redirect-http-to-https.html (Method 1)
and
https://blogs.msdn.microsoft.com/kaushal/2013/05/22/http-to-https-redirects-on-iis-7-x-and-higher/ (Method 1)
I used the below setting in configuration file of the test application,
<rule name="HTTP to HTTPS redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
However, the issue is, after adding the below code, when user tries to access the test site using http in url, it automatically redirects to https, but to the non-test site (i.e. PersonalCorner) and not the test application, which is confusing.
Can anyone let me know what mistake I am doing in the above setting? I want to implement autoredirect only for the test application.
Answering my query myself!
The below configuration fixed the issue,
<rewrite>
<rules>
<rule name="Redirect to https" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" appendQueryString="false" />
</rule>
</rules>
</rewrite>
Reference: How to force HTTPS using a web.config file

Using IIS Rewrite URL for SEO to move all Cold Fusion CFM pages to ASP aspx pages

I am moving a large database driven website from coldfusion .cfm to .net aspx. I am pretty much finished now, but I need to do 301 redirects on all the coldfusion pages to the new aspx ones, so google and such like as we don't want to lose the search engine positioning. So I intended to use URL Rewrite for this, but I cannot get it working, most of the time I just get 404s back.
Basically, my new aspx pages are all the same filename, just .cfm is replaced with .aspx, some pages can have a long querystring after them and some not.
Examples:
http://www.example.com/test.cfm needs to be remapped to http://www.example.com/test.aspx
http://www.example.com/test2.cfm?a=1&b=2&c=3 needs to be remapped to http://www.example.com/test2.aspx?a=1&b=2&c=3
The site itself has hundreds of pages and some pages have over 8 variables in the querystring, so I just wanted to try and do a straight map over in URL rewrite. I cannot do a rule per page as that will take ages!
My current attempt is:
<rule name="redirect all requests" stopProcessing="true">
<match url="^(.*)$" ignoreCase="true" />
<conditions logicalGrouping="MatchAll">
<add input="{URL}" pattern="^http://www.example.com/(.*).cfm(.*)$" />
</conditions>
<action type="Redirect" url="http://www.example.com/{C:1}.aspx" appendQueryString="true" logRewrittenUrl="true" />
</rule>
This just does a 404 for me. Obviously the cfm pages do not exist and the aspx ones now do. I still have cold fusion installed on the server for now, and do not want to uninstall it until google has updated itself (it case of issues so I can always go back).
Any help would be much appreciated.
Thanks
David
It's like this...
<rule name="CFM301ASP" stopProcessing="true">
<match url="^(.*)$" />
<conditions>
<add input="{REQUEST_FILENAME}" pattern="^.*\.cfm$" negate="false" ignoreCase="true" />
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
</conditions>
<action type="Redirect" url="/yourfile.aspx" appendQueryString="true" redirectType="Permanent" />
</rule>
This only works on CFMs that do not exist (isFile=false). It will 301 redirect CFMs that would cause a 404, to your ASP file, and append the URL variables.
The documentation seems to cover all of this.
From the docs on HTTP Redirect:
<configuration>
<system.webServer>
<httpRedirect enabled="true" exactDestination="true" httpResponseStatus="Found">
<add wildcard="*.php" destination="/default.htm" />
</httpRedirect>
</system.webServer>
</configuration>
This led me to believe that you should be able to map URLs from one file extenstion to another.
Creating Rewrite Rules for the URL Rewrite Module
<rewrite>
<rules>
<rule name="Rewrite to article.aspx">
<match url="^article/([0-9]+)/([_0-9a-z-]+)" />
<action type="Rewrite" url="article.aspx?id={R:1}&title={R:2}" />
</rule>
</rules>
</rewrite>
Try reading through these docs, you should be able to find the correct syntax that will allow you to just transfer from *.cfm to *.aspx, passing along the same query strings, or making translations as needed.

http to https rewrite too many redirect loops IIS 7

I have application which I have hosted in IIS 7.0.
Where I have to make sure that it works only on HTTPS and not on HTTP
so I have included below rule in my root config.
<rewrite>
<rules>
<rule name="HTTP to HTTPS redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Found" />
</rule>
</rules>
</rewrite>
After adding this rule when i tried to access my application I get below error:
Page has resulted in too many redirects. Clearing your cookies for
this site or allowing third-party cookies may fix the problem. If not,
it is possibly a server configuration issue and not a problem with
your computer. Here are some suggestions: Reload this web page later.
Learn more about this problem.
We have our ASP.NET application hosted on AWS with Elastic Load Balancing, and the rule in the question with the accepted answer did not work for us, and kept causing infinite redirects.
This is the rule that finally worked for us:
<rewrite>
<rules>
<rule name="HTTPS Rule behind AWS Elastic Load Balancer Rule" stopProcessing="true">
<match url="^(.*)$" ignoreCase="false" />
<conditions>
<add input="{HTTP_X_FORWARDED_PROTO}" pattern="^http$" ignoreCase="false" />
</conditions>
<action type="Redirect" url="https://{SERVER_NAME}{URL}" redirectType="Found" />
</rule>
</rules>
</rewrite>
Put below input condition:
<add input="{HTTPS}" pattern="on" />
Instead of:
<add input="{HTTPS}" pattern="off" />
My case, I needed to put like this:
<rewrite>
<rules>
<rule name="HTTP to HTTPS redirect" stopProcessing="true">
<match url="(.*)" ignoreCase="false" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTP_X_FORWARDED_PROTO}" pattern="^http$" />
<add input="{HTTPS}" pattern="on" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Found" />
</rule>
</rules>
I also faced that problem. All requests to the server were HTTP.
In my case problem was that I use Cloudflare DNS.
There is SSL/TLS setting that by default SSL/TLS encryption mode is set to Flexible.
Make sure to change the mode to Full.
Also as was mentioned by SNag we had a site that is sitting behind an ELB on Amazon. Attempting to apply a rewrite rule without the following input header was causing infinite redirects. This appears to be a result of needing the input type being HTTP_X_FORWARDED_PROTO as in the following: <add input="{HTTP_X_FORWARDED_PROTO}" pattern="^http$" ignoreCase="false" />.
From AWS documentation "Your application or website can use the protocol stored in the X-Forwarded-Proto request header to render a response that redirects to the appropriate URL." We are using the ELB with DNS entries to forward to the server with the site on it.
For IIS 10 (Windows Server 2016) I have followed instructions from here which generate a slightly different XML configuration for the rewrite:
<rewrite>
<rules>
<rule name="HTTP 2 HTTPS" patternSyntax="Wildcard" stopProcessing="true">
<match url="*" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTPS}" pattern="off" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Found" />
</rule>
</rules>
</rewrite>
The pattern is off and the match is only *.
I am using Liquid Web Cloud Sites, and ran into the exact same issue.
I tried the solution here, but it didn't work for what I needed because of this condition:
<add input="{HTTPS}" pattern="off" />
As the OP has it, this means is, "match and implement this rule when HTTPS is off". And the accepted solution for this question just inverts this, and matches the rule when HTTPS is on. It solved the infinite loop issue, but only because my rule was incorrectly matched - I actually only want to change the request to HTTPS when HTTPS is off. Thus none of my HTTP requests were getting forwarded.
Interestingly, none of my HTTPS requests were getting forwarded either, and from this (and a few other tests I did) I determined that although the browser shows HTTPS, the server is treating it like an HTTP request. Thus the server always believes it is receiving an HTTP request, and always ignored the rule (which now specified only match requests where HTTPS is on - i.e. never).
Hours of research and tests later, I deduced that its a similar issue as described here, summarised here:
To reduce costs [many hosting providers install the] SSL certificate on the TMG Gateway and this gateway is simply rewriting the request to standard HTTP when passing it to the actual web server. So by the time the request hits IIS and your web application it is a standard plain HTTP request.
.
TLDR;
Eventually I spoke to the team at Liquid Web who pointed me in the direction of a help article buried in their own site which solved the issue. They suggested I use the following rewrite rule which fixed it:
<system.webServer>
<rewrite>
<rules>
<rule name="Redirect to HTTPS" stopProcessing="true">
<match url=".*"/>
<conditions>
<add input="{HTTP_CLUSTER_HTTPS}" pattern="^on$" negate="true"/>
<add input="{HTTP_CLUSTER_HTTPS}" pattern=".+" negate="true"/>
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{SCRIPT_NAME}" redirectType="SeeOther"/>
</rule>
</rules>
</rewrite>
</system.webServer>
I hope this might work for others in a similar situation.
Original liquidweb help article
If you use cloudflare for SSL , put it on Full mode
Cloudflare -> SSL/TLS -> Overview -> Full
Figure
I figured out something regarding this issue. Basically, if the incoming request is HTTPS do nothing.
<rule name="No Redirect if https" enabled="true" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAny" trackAllCaptures="false">
<add input="{HTTPS}" pattern="^ON$" />
</conditions>
<action type="None" />
</rule>
<rule name="Redirect to https" enabled="true" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{HTTP_HOST}" pattern="^\example\.com$" />
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{R:0}" />
</rule>

ASP.NET - rewriting all https requests to http

My issue is precisely the one presented here, and I've decided to try rewrite all https requests to http. I've searched long and hard but there doesn't seem to be a definitive way to achieve this - see these questions (no solutions): Redirect https to http using rewrite rule in webconfig file ; https://stackoverflow.com/questions/15214717/iis-rewrite-https-to-http-whilst-keeping-existing-https-rules
I've added the rewrite module to IIS, and tried the following in web.config:
<rewrite>
<rules>
<clear />
<rule name="force http" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="http://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
But it still allows the user to access a non-https site with https (essentially accessing a different site).
How do I force all https requests to be http requests?
edit: I've also tried every suggested solution here with no luck. The url rewrite module is definitely successfully installed on IIS!
edit2: Tried the following without success:
<system.webServer>
<rewrite>
<rules>
<clear />
<rule name="force http" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll">
<add input="{HTTPS}" pattern="on" ignoreCase="true" />
<add input="{HTTP_HOST}" pattern="^(?:www)?\.test.site\.com$"
negate="true" ignoreCase="true" />
</conditions>
<action type="Redirect" url="http://{HTTP_HOST}{REQUEST_URI}"
redirectType="Permanent" />
</rule>
</rules>
</rewrite>
</system.webServer>
I restarted IIS and the rewrite rules reflect in inetmgr. Loading https://test.site.com/ still loads with https.
A couple of things. First the rewrite needs to process when HTTPS is on and not off. Second, for the application that needs to run over HTTPS you will need to exclude it from the rewrite. The revised rewrite rule should look something like this:
<rewrite>
<rules>
<clear />
<rule name="force http" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll">
<add input="{HTTPS}" pattern="on" ignoreCase="true" />
<add input="{HTTP_HOST}" pattern="^example\.com$"
negate="true" ignoreCase="true" />
</conditions>
<action type="Redirect" url="http://{HTTP_HOST}{REQUEST_URI}"
redirectType="Permanent" />
</rule>
</rules>
</rewrite>
This should keep https://example.com/login on https and all other URL's will get redirected to http. For example, https://test.example.com/login will be redirected to http://test.example.com/login. This rewrite rule needs to be placed on the site with the HTTPS binding for the rewrite to work properly.
Please be aware when using a 301 permanent redirect some browsers won't make the request out to the server on subsequent hits so after changing the rule a browser cache clear is required. The network tab may even lie and say the request is made but an external tool like Fiddler or Wireshark will let you know for sure.

Resources