使用HttpModule實現(xiàn)多個域名分別“綁定”到子目錄

2010-08-28 10:48:52來源:西部e網(wǎng)作者:

目前虛擬主機商提供將多個域名綁定到站點根目錄,但是不提供類似cpanel那樣可以將域名綁定到站點的子目錄。
而當你手上有多個域名,網(wǎng)站空間和流量又有閑置的時候,是很希望
將這些資源利用起來,而且要做到降低做站的成本。而網(wǎng)絡上流傳的多域名綁到子目錄多為判斷HTTP_HOST再使用Asp的Response.Redirect或者php的header方法重訂向到子目錄去。這種方法在地址的請求上發(fā)生了變化,大家都知道Redirect的定向是很不友好的,在服務器端控制自動跳轉會令訪問者感到不安。
所以我需要的是對這個域名下面的所有請求都轉接到對應的子目錄里去
比如

http://www.xaradio.com/default.aspx
實際訪問的是http://www.3pub.com/xaradio/default.aspx

http://www.xaradio.com/album.aspx?id=722
實際訪問的是http://www.3pub.com/xaradio/album.aspx?id=722

http://www.xaradio.com/*.aspx
實際要訪問到http://www.3pub.com/xaradio/*.aspx

而綁定到該站點根目錄的其他域名和地址仍然不受影響
如: http://www.3pub.com/ 和http://3pub.com/
 http://www.3pub.com/default.aspxhttp://3pub.com/default.aspx


http://www.aspxboy.com/484/default.aspx該文章詳細的描述了在Asp.Net中使用HttpModule和HttpHander來重寫Url,讀懂他特別是http://www.aspxboy.com/484/archive.aspx#ekaa節(jié)將是我們下面工作的前提朋友們可以下載該文章附帶的代碼研究。

如果您對HttpModule的編成非常熟悉那么可以向下進行了

一。 先把配置文件從web.config內(nèi)移出為了不讓web.config變的非常臃腫,我們將配置文件從web.config內(nèi)移出
假設我們的多域名綁定配置文件為“MulitDomain.config“
將RewriterConfiguration.cs的public static RewriterConfiguration GetConfig()方法
修改如下:

/// 
/// 從XML配置文件中返回重寫信息
/// 
/// RewriterConfiguration
public static RewriterConfiguration GetConfig()
{
RewriterConfiguration config = (RewriterConfiguration) BoovooCache.Get(CacheKey);
if(config == null)
{
// 2005-08-18 wu meibo update the config file to SiteUrls.config
// HttpContext.Current.Cache.Insert("RewriterConfig", ConfigurationSettings.GetConfig("RewriterConfig"));

///************************************************************************************
///  
///  Author:活靶子,huobazi
/// Date:2005-08-18
///
///  Description:將配置文件移到單獨的文件內(nèi),更新以下代碼,原代碼(上一行)停止工作
///
///************************************************************************************

string filePath = String.Empty;
if(HttpContext.Current != null)
{
filePath = HttpContext.Current.Server.MapPath("~/MulitDomain.config");
}
else
{
filePath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "MulitDomain.config";
}

XmlSerializer ser = new XmlSerializer(typeof(RewriterConfiguration)); 
FileStream fileReader = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); 
StreamReader reader = new StreamReader(fileReader); 
config = (ser.Deserialize(reader)) as RewriterConfiguration; 
reader.Close(); 
fileReader.Close(); 
if (File.Exists(filePath)) 
{ 
CacheDependency dep = new CacheDependency(filePath); 
BoovooCache.Max(CacheKey,config,dep); 
BoovooCache.ReSetFactor(config.CacheFactor);
} 
}

return config;
} 
二。做一些修補
RewriterModule.cs內(nèi)
public virtual void Init(HttpApplication app) 
{

///**********************************************************************************
///  Author:活靶子,huobazi
/// Date:2005-08-18
///  Description:增加BeginRequest,在內(nèi)增加防止黑客可能利用的某些Url漏洞攻擊的代碼
///**********************************************************************************

app.BeginRequest += new EventHandler(this.RewriterModule_BeginRequest);

// 警告!此代碼不適用于 Windows 身份驗證!
// 如果使用 Windows 身份驗證,
// 請改為 app.BeginRequest

app.AuthorizeRequest += new EventHandler(this.RewriterModule_AuthorizeRequest);


} 
protected virtual void RewriterModule_BeginRequest(object o , EventArgs e)
{
HttpApplication app = ((HttpApplication)(o)); 
HttpServerUtility Server = app.Server; 
HttpRequest Request = app.Request; 

///************************************************************
///  Author:活靶子,huobazi
/// Date:2005-08-18
/// Description:修補黑客可能采用".."的方法進入其他目錄的問題
///************************************************************

string strURL = Server.UrlDecode(Request.RawUrl); 
if (strURL.IndexOf("..") != -1) 
{ 
throw new HttpException(404, "Not Found"); 
} 

///**********************************************************************************
///  Author:活靶子,huobazi
/// Date:2005-08-18
/// Description:修補"規(guī)范化"問題 see: http://support.microsoft.com/?kbid=887459
///***********************************************************************************

if (Request.Path.IndexOf('\\') >= 0 ||
Path.GetFullPath(Request.PhysicalPath) != Request.PhysicalPath) 
{
throw new HttpException(404, "Not Found");
}
} 
三。開始匹配域名
protected void Rewrite(string requestedPath, System.Web.HttpApplication app)
{
string host = app.Context.Request.Url.Host.ToString().ToLower();

app.Context.Trace.Write("RewriterModule", "Entering ModuleRewriter");   
RewriterRuleCollection rules = RewriterConfiguration.GetConfig().Rules; 
for(int i = 0; i < rules.Count; i++)
{//將MulitDomain.config內(nèi)定義的規(guī)則LookFor的值逐個匹配當前主機名判斷否被定義了需要重寫
//如果匹配則需要重寫,那將請求重寫到SendTo定義的目錄內(nèi)的該文件
string lookFor = "^" + rules[i].LookFor + "$";
//string lookFor = "^" + Rewriter.ResolveUrl(app.Context.Request.ApplicationPath, rules[i].LookFor + requestedPath) + "$";
Regex re = new Regex(lookFor, RegexOptions.IgnoreCase);
if (re.IsMatch(host))
{
string sendToUrl = Rewriter.ResolveUrl(app.Context.Request.ApplicationPath,  rules[i].SendTo + requestedPath);
app.Context.Trace.Write("RewriterModule", "Rewriting URL to " + sendToUrl);
Rewriter.RewriteUrl(app.Context, sendToUrl);
break;
}
} 
app.Context.Trace.Write("RewriterModule", "Exiting ModuleRewriter");
}
四。寫規(guī)則文件
MulitDomain.config的匹配規(guī)則如下:
<?xml version="1.0" encoding="utf-8" ?>
 <RewriterConfig>
 <Rules>
  <RewriterRule>
   <LookFor>www\.xaradio\.com</LookFor>
   <SendTo>~/xaradio</SendTo>
  </RewriterRule>
  <RewriterRule>
   <LookFor>xaradio\.com</LookFor>
   <SendTo>~/xaradio</SendTo>
  </RewriterRule>
 </Rules>
  </RewriterConfig>
最后說明一下,根目錄下一定要有一個Default.aspx如果你的所有域名都按照這種方式“綁定”那么根目錄下放置一個空Default.aspx就可以,該文件來“欺騙IIS” ,防止直接使用域名訪問的時候IIS查找不到default或者index文件就報404錯誤,等到該檢查過去之后權利已經(jīng)移交到aspnet_isapi.dll那里了。
關鍵詞:ASP.NET

贊助商鏈接: