Serve specific page according to domain name - asp.net

We have a clients domain name (d1) pointing at one of our sites (s1) which is a .NET 4 web forms site.
The client has set up a subdomain on a different domain (d2) and pointed this at the s1 IP address.
We need to serve a specific page on s1 if the d2 domain is used and not have the page in the URL.
I would like to achieve this without a redirect if possible.
eg
example.com -> the site
x.example.net -> the site /thepage.aspx (but want the URL in the address bar to remain x.example.net, not x.example.net/thepage.aspx).
I've tried doing a Server.Transfer in begin request and while this worked, the postback didn't (I assume because it's because of the transfer but I don't know how to detect a postback in begin request and thus not transfer).
I thought there may be a way to leverage routing but there would be no path (just the domain name) so any route set up like this would presumably route all requests to this page if they don't get caught be a previous route - not ideal).
So, in short:
Is there a way to detect a postback in Application_BeginRequest in global.asax so I only transfer the inital request?
Or is there a way of mapping a domain name to a page without redirecting?
Is there some feature I don't know about that achieves this?

You can set up Rewrite Rules to do this. The following rule rewrites the root Url to /thepage.aspx only if the host matches x.example.net.
RewriteCond %{HTTP_HOST} (^x.example.net$)
RewriteRule ^$ / [NC,L]
If you have IIS7: you can do this using URL Rewrite.
If you have IIS6: you can set up ISAPI Rewrite on the server.
Depending on your setup, the 2nd line may include a slash:
RewriteRule ^/$ /thepage.aspx [NC,L]

You could write a HttpModule which examines incoming requests - if a request is for x.domain2.com, then you could invoke thepage.aspx like this:
Type page_type = BuildManager.GetCompiledType ("~/thepage.aspx");
Page page = (Page) Activator.CreateInstance (page_type);
page.ProcessRequest (Context);

Related

How to redirect with nginx but keep the old url

I have mainsite.com and a subdomain sub.mainsite.com.
The sub.mainsite.com has a cname record point to another online content web
Right now I will to redirect mainsite.com/sub to display the sub.mainsite.com content, but still keep the mainsite.com/sub URL.
How can I do that with Nginx?
You cannot do that. You can either redirect using return or rewrite directive. Either way, the URL is redirected. The difference is you can reframe the URL as required using rewrite directive.

nginx redirect to hashbang URL without URL encoding

I have a rewrite rule that looks like the following
rewrite ^/([a-zA-Z0-9_]+)$ /mysite/#!/$1/login;
The idea is that a shortcode like
/foo
gets redirected to
/mysite/#!/foo/login
However nginx is redirecting to:
/mysite/%23!/foo/login
How do I prevent the URL encoding from happening in the rewrite?
I can reproduce this issue by using a reverse proxy.
Nginx is actually doing the right thing, as # is a reserved character for URIs and identifies the start of the fragment identifier.
The fragment identifier is for the browser's use only and is not usually received by the server in the requested URL. I am not sure how your Tomcat server is receiving requests containing a naked # in the first place.

strange 401 error appears for some urls when using .htaccess to redirect http to https

OK, here is the 7th day of unsuccessfull attempt to find an answer why 401 error appears...
Now,
.htaccess in the root folder contains the only 3 strings (was simplified) and there are NO more .htaccess files in the project:
RewriteEngine On
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
So, it redirects all requests to be https. It works fine for any urls, even for /administration directory.
So,
http://mydomain.com
becomes
https://mydomain.com
If https://mydomain.com was entered, there are no redirections.
http://mydomain.com/administration/index.php
becomes
https://mydomain.com/administration/index.php
If https://mydomain.com/administration/index.php was entered, there are no redirections.
That's clear, and the problem is below.
I want /administration directory to be password protected. My Shared Hosting Control Panel allows to protect directories without manual creating of .htaccess and .htpasswd (you choose a directory to protect, create username and password, and .htaccess and .htpasswd are created automatically). So, .htaccess appears in the /administration folder. .htpasswd appears somewhere else, the path to .htpasswd is correct, and everything looks correct (it works the same way as to create it manually). So, there are 2 .htaccess files in the project, one in the root directory and one in the /administration directory (with .htpasswd at the directory .htaccess knows where it is).
Once the password is created,
the results are:
You enter:
https://mydomain.com/administration/index.php
Then it asks to enter a password.
If you enter it correctly,
https://mydomain.com/administration/index.php is displayed.
The result: works perfect.
But, if you enter
http://mydomain.com/administration/index.php (yes, http, without S)
then instead of redirecting to the same,but https page,
it redirects to
https://mydomain.com/401.shtml (starts with httpS)
by unknown reason and even does NOT ask a password. Why?
I've contacted a customer support regarding this question and they are sure the problem is in .htaccess file, and they do not fix .htaccess files (that's clear, they do not, I don't mind).
Why does this happen?
Did I forget to put some flags, or some options to change default settings in the .htaccess file?
P.S.Creating .htaccess and .htpasswd manually (not from hosting Control Panel) for the folder /administration causes the same 401 error in case if not https, but http was entered.
And the problem appears with URLs to /administration directory only.
Thank you.
Try using this instead. Not the L and R flag.
RewriteEngine On
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Also clear your browsers cache first, to remove the old incorrect redirect.
If that doesn't work try using this.
RewriteCond %{HTTPS} !on
RewriteCond %{THE_REQUEST} ^(GET|HEAD)\ ([^\ ]+)
RewriteRule ^ https://%{HTTP_HOST}%2 [L,R=301]
I feel a bit bad about writing it, as it seems kind of hackish in my view.
EDIT
Seems the 2nd option fixed the problem. So here is the explanation as to why it works.
The authentication module is executed before the rewrite module. Because the username and password is not send when first requesting the page, the authentication module internally 'rewrites' the request url to the 401 page's url. After this mod_rewrite comes and %{THE_REQUEST} now contains 401.shtml instead of the original url. So the resulting redirect contains the 401.shtml, and not the url you want.
The get to the original (not 'rewritten') url, you need to extract it from %{THE_REQUEST}. THE_REQUEST is in the form [requestmethod] [url] HTTP[versionnumber]. The RewriteCond extracts just the middle part ([url]).
For completeness I added the [L,R=301] flags to the second solution.
I think I found an even better solution to this!
Just add this to your .htaccess
ErrorDocument 401 "Unauthorized"
Solution found at:
http://forum.kohanaframework.org/discussion/8934/solved-for-reall-this-time-p-htaccess-folder-password-protection/
-- EDIT
I eventually found the root cause of the issue was ModSecurity flagging my POST data (script and iframe tags cause issues). It would try to return a 401/403 but couldn't find the default error document because ModSecurity had made my htaccess go haywire.
Using ErrorDocument 401 "Unauthorized" bypassed the missing error document problem but did nothing to address the root cause.
For this I ended up using javascript to add 'salt' to anything which was neither whitespace nor a word character...
$("form").submit(function(event) {
$("textarea,[type=text]").each(function() {
$(this).val($(this).val().replace(/([^\s\w])/g, "foobar$1salt"));
});
});
then PHP to strip the salt again...
function stripSalt($value) {
if (is_array($value)) $value = array_map('stripSalt', $value);
else $value = preg_replace("/(?:foobar)+(.)(?:salt)+/", "$1", $value);
return $value;
}
$_POST = stripSalt($_POST);
Very, Very, Very Important Note:
Do not use "foobar$1salt" otherwise this post has just shown hackers how to bypass your ModSecurity!
Regex Notes:
I thought it may be worth mentioning what's going on here...
(?:foobar)+ = match first half of salt one or more times but don't store this as a matched group;
(.) = match any character and store this as the first and only group (accessible via $1);
(?:salt)+ = match second half of salt one or more times but don't store this as a matched group.
It's important to match the salt multiple times per character because if you've hit submit and then you use the back button you will go back to the form with all the salt still in there. Hit submit again and more salt gets added. This can happen again and again until you end up with something like:
foobarfoobarfoobarfoobar>saltsaltsaltsalt
I was not satisfied with the solutions above so I came up with another one:
In a modern web server configuration we should redirect all traffic to HTTPS so the user can not reach any content without HTTPS. After the user's browsing our content with HTTPS we can use authentication. With this in mind we can wrap the authentication directive in an If directive:
<If "%{HTTPS} == 'on'">
AuthType Basic
...
</If>
You can leave and use Rewrite directives as you like.
With this solution:
you must not change ErrorDocument as suggested by Hoogs
you must not extract path from THE_REQUEST in a hackish way as suggested by Gerben
This is the type of thing is that is a bit tricky to troubleshoot on Apache without the box right in front of you, but I what I think is happening is that your rewrite directive is being processed after path resolution, and it's the path resolution that has the password requirement.
Backing up a bit, the way a URL is resolved in Apache is that the request comes in and gets handed from module to module, kind of like a bucket brigade. Each module does its own thing....some modules do content negotiation, some translate URLs to file paths, some check authentication, one of them is mod_rewrite ...
One place where you see this in the configuration is actually that there is both a Location directive and a Directory directive which seem the same in most respects, but they are different because Locations talk about URLs and Directories talk about filesystem paths.
Anyhow, my guess is that going down the bucket brigade, Apache figures out that it needs a password to access that content before it figures out that it needs to redirect to HTTPS. (mod_rewrite is kind of a crazy module and it can mess with all kinds of things in surprising ways..it can do path translation, bits and pieces of rewrite, make subrequests, and a bunch of other nutty things).
There are few ways you can fix this that I can think of.
Change your directory root in the vhosts container for the http site so that it can't find the passworded file (this would be my approach)
Change your module load order so that mod_rewrite happens earlier in the chain (may have unexpected consequences)
Use setenvif
That last one needs more explanation. Remember the bucket brigade I told you about? Apache modules can also set environment variables, which are completely outside of the module->module->module->chain. You could, perhaps, set an environment variable if the site is not HTTPS. Then however you set up your access control could use the SetEnvIf directive to always allow access to the resource if it's set, BUT you have to make sure for sure that you're going to hit that rewrite rule.
As I said, my choice would #1 but sometimes people need to do crazy things, and Apache will let you.
My real-world SOP for https:// sites these days is that I just shoot all of my port 80 content over to a single vhost that can't serve any content at all. Then i mod_rewrite everything over https://... badda bing, badda boom, no http and no convoluted security risks.

Add SSL *only* to specific folder

I want to redirect users to the SSL secure server when they are accessing the 'Account' section of the site which will contain the forms for user profiles, settings, etc. However, I don't want users being able to access the rest of the site on the SSL server. Because of how I coded my templates, I have my paths set as <a href="/about"> as an example. If they are in the Account section and click a link to the About section, they would still be on the secure https: connection. Obviously, I can just hard code the links to link to the http:// server, but I'm looking for alternatives.
So far I have the following in my .htaccess and it is working, but I'm wondering if this more resource intensive than it needs to be? Is it better to hardcode links to any of the other 'non-account' sections, or is doing this via .htaccess a good way to go about it?
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond $1 ^(account) [NC]
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTPS} on
RewriteCond $1 ^(about|terms|products) [NC]
RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Also, if I wanted to prevent the homepage from being accessed via https:// how would I go about adding that to my .htaccess file?
I would actually suggest to avoid to use rewrite rules for this.
The problem with rewrite rules that turn http requests into https requests is that they're in fact redirections. This means that for every http request that is to be turned into an https request, the browser is first going to make the full http request (including content, cookies, except secure ones), get the redirection code from the server and then make the request again to the https re-written URL.
Although this is convenient, if you rely on this instead of making sure the links on your site that are intended to be to https sections are indeed using https, it will make it hard to detect when those link are incorrectly redirecting to the http variant.
The typical consequences are:
mixed content warnings if you embed something using an http linked later turned automatically and transparently into https, which is a bad thing; and
possible leakage of data.
Instead, I would suggest that you don't use automatic rewrite/redirects and make sure the sections that are meant to be available via HTTPS only are not available at all on the plain HTTP variant (i.e. http://yourhost/account should return 404s): this will at least force you to notice when you've incorrectly linked and help you spot where you could have a security issue. Ultimately, although they share the same host name, an http site and and https site can have two distinct URL spaces: it's not a bad thing in this context.
The only case I see where rewrites from http to https are really useful are when you want to make sure the user's entry point to your site is redirected.
Rewrites from https to http don't present this problem of course.

How does url rewrite works?

How does web server implements url rewrite mechanism and changes the address bar of browsers?
I'm not asking specific information to configure apache, nginx, lighthttpd or other!
I would like to know what kind of information is sent to clients when servers want rewrite url?
There are two types of behaviour.
One is rewrite, the other is redirect.
Rewrite
The server performs the substitution for itself, making a URL like http://example.org/my/beatuful/page be understood as http://example.org/index.php?page=my-beautiful-page
With rewrite, the client does not see anything and redirection is internal only. No URL changes in the browser, just the server understands it differently.
Redirect
The server detects that the address is not wanted by the server. http://example.org/page1 has moved to http://example.org/page2, so it tells the browser with an HTTP 3xx code what the new page is. The client then asks for this page instead. Therefore the address in the browser changes!
Process
The process remains the same and is well described by this diagram:
Remark Every rewrite/redirect triggers a new call to the rewrite rules (with exceptions IIRC)
RewriteCond %{REDIRECT_URL} !^$
RewriteRule .* - [L]
can become useful to stop loops. (Since it makes no rewrite when it has happened once already).
Are you talking about server-side rewrites (like Apache mod-rewrite)? For those, the address bar does not generally change (unless a redirection is performed).
Or are you talking about redirections? These are done by having the server respond with an HTTP code (301, 302 or 307) and the location in the HTTP header.
There are two forms of "URL rewrite": those done purely within the server and those that are redirections.
If it's purely within the server, it's an internal matter and only matters with respect to the dispatch mechanism implemented in the server. In Apache HTTPD, mod_rewrite can do this, for example.
If it's a redirection, a status code implying a redirection is sent in the response, along with a Location header indicating to which URL the browser should be redirected (this should be an absolute URL). mod_rewrite can also do this, with the [R] flag.
The status code is usually 302 (found), but it could be configured for other codes (e.g. 301 or 307).
Another quite common use (often unnoticed because it's usually on by default in Apache HTTPD) is the redirection to the the URL with a trailing slash on a directory. This is implemented by mod_dir:
A "trailing slash" redirect is issued
when the server receives a request for
a URL http://servername/foo/dirname
where dirname is a directory.
Directories require a trailing slash,
so mod_dir issues a redirect to
http://servername/foo/dirname/.
Jeff Atwood had a great post about this: http://www.codinghorror.com/blog/2007/02/url-rewriting-to-prevent-duplicate-urls.html
How web server implements url rewrite mechanism and changes the address bar of browsers?
URL rewriting and forwarding are two completely different things. A server has no control over your browser so it can't change the URL of your browser, but it can ask your browser to go to a different URL. When your browser gets a response from a server it's entirely up to your browser to determine what to do with that response: it can follow the redirect, ignore it or be really mean and spam the server until the server gives up. There is no "mechanism" that the server uses to change the address, it's simply a protocol (HTTP 1.1) that the server abides by when a particular resource has been moved to a different location, thus the 3xx responses.
URL rewriting can transform URLs purely on the server-side. This allows web application developers the ability to make web resources accessible from multiple URLs.
For example, the user might request http://www.example.com/product/123 but thanks to rewriting is actually served a resource from http://www.example.com/product?id=123. Note that, there is no need for the address displayed in the browser to change.
The address can be changed if so desired. For this, a similar mapping as above happens on the server, but rather than render the resource back to the client, the server sends a redirect (301 or 302 HTTP code) back to the client for the rewritten URL.
For the example above this might look like:
Client request
GET /product/123 HTTP/1.1
Host: www.example.com
Server response
HTTP/1.1 302 Found
Location: http://www.example.com/product?id=123
At this point, the browser will issue a new GET request for the URL in the Location header.

Resources