如何让博客/WordPress/Tumblr允许用户掩盖URL

14

我正在创建一个saas应用程序。用户有自己的网址,如user.mysaasapp.com。

为了让用户拥有自己的网址,我使用 mod rewrite。例如:http://mysaasapp.com/?user=user 变成 user.mysaasapp.com(这部分已经完美运作)

现在,我想给用户灵活性,让他们掩盖他们的网址。这意味着用户可以将他们的子域名 (saas.theirdomain.com)指向 user.mysaasapp.com。我该如何做到这一点?

我阅读了许多关于此问题的文章(cname),但仍然没有确定解决方案。我想知道像WordPress/Google这样的大公司是如何做到的。

例如:http://www.tumblr.com/docs/en/custom_domains

例如:http://developer.uservoice.com/docs/site/domain-aliasing/

我意识到公司需要执行以下步骤:

  1. 让用户添加CNAME记录
  2. 让用户在 saas 应用程序中输入其域名(可能在自定义域名下)

我需要做些什么才能使这个功能工作?谢谢!


嗨,以下的答案都不能工作。我没有一个名为User的文件夹。文档根目录是/var/www/user。如果有人能够给我一些启示,我将不胜感激!请注意,我正在使用的是http://mysaasapp.com/?user=user来访问user.mysaasapp.com。 - Slay
你可以尝试做以下操作:
  1. 在一个域-用户映射表中保存用户的自定义域名。
  2. 每当用户访问自定义域名时,添加一个规则来检查像usermapping.php这样的页面。
  3. 在usermapping.php中获取该域名的用户映射,然后相应地显示内容。
- Virendra
@EaterOfCorpses 无法使其正常工作。我认为这是我的服务器虚拟主机配置问题。我使用 cpanel 子域功能创建了一个通配符 *。那么它会自动生成:<VirtualHost *:80> ServerName mysaasapp.com ServerAlias *.mysaasapp.com DocumentRoot /var/www/user </VirtualHost> - Slay
你应该尝试一下,我不太熟悉 cPanel。我有一个 cPanel 网站,但目前没有凭据,但我认为它应该可以工作,否则您需要添加一个带有“*.mysaasapp.com”的停放域。 - EaterOfCode
5个回答

4
如果我没记错的话,在 ServerAlias 中,您可以使用通配符,并且通过 mod_rewrite 模块将其重写为正确的文件,因此您的虚拟主机会像这样:
<VirtualHost *:80>
    ServerName mysaasapp.com
    ServerAlias *.mysaasapp.com
    DocumentRoot /var/www/user
</VirtualHost>

你的CNAME应该像这样

*.mysaasapp.com IN CNAME mysaasapp.com

希望这可以帮到你。

编辑:

将虚拟主机更改为以下内容

<VirtualHost *:80>
    ServerName mysaasapp.com
    ServerAlias *.mysaasapp.com
    DocumentRoot [STANDARDFOLDER]
</VirtualHost>

请将[STANDARDFOLDER]替换为mysaasapp.com的DocumentRoot

在您的index.php顶部放置以下内容:

// Array with all the subdomains who doesn't belong to users
$_notUsers = array("www");
// No code without a Boom,
$_domainParts = explode('.',$_SERVER[HTTP_HOST],-2);
// Check if subdomain is legit
if(!in_array($_domainParts[0],$_notUsers) && !empty($_domainParts)){
    // get the real subdomain structure
    $_sub = str_replace('.mysaasapp.com','',$_SERVER['HTTP_HOST']);
    // Don't look at this it's horrible :'( but this makes it think that there is 
    // something in user 
    $_GET['user'] = $_sub;
    // I dont know where you want it in the question its index.php and in comment its 
    // user.php so change this as you want it
    include 'user.php';
    // Exit so we dont have an user page and homepage together but only when
    // using user.php comment this out when using index.php
    exit;
// end
}

这是一种非常简陋的解决方案,希望现在它可以解决您的问题。

更新:

起初我并不知道您还想从自定义域名进行重定向,

然后他们需要在DNS服务器/管理器中添加CNAME记录

theirdomain.com IN CNAME thierusername.mysaasapp.com

如果您的DNS记录使所有子域名都指向您的apache,那么应该使用我给您的代码和Vhosts来工作。
更新2: lanzz刚刚指出我忘了一件事(扇面),我正在检查HOST头,这是没有意义的,因为它将具有customdomain.com,所以您需要询问用户的域名(如果您没有共享IP,请让他们使用CNAME进行指向,如果您没有共享IP,您可以让他们使用A记录指向您的IP),并从HTTP_HOST中查找该域名,并在数据库中搜索该域名,之后它就应该工作了!
稍微编辑过的代码:
//first look if you're on your own domain,
// also again an Array with all the subdomains who doesn't belong to users
$_notUsers = array("www");
//lets explode the domain 
$_domainParts = explode(".",$_SERVER["HTTP_HOST"]);
//get length of $_domainParts
$_domainPartsLength = count($_domainParts);
//get last two parts (little bit ugly but there are uglier ways)
$_currentDomain = $_domainParts[$_domainPartsLength-1] . "." . $_domainParts[$_domainPartsLength-2];
//time to check if it's yours and if it's legit
if($_currentDomain == "mysaasapp.com"){
    if(!in_array($_domainParts[0],$_notUsers) && !empty($_domainParts)){
        // get the real subdomain structure
        $_sub = str_replace('.mysaasapp.com','',$_SERVER['HTTP_HOST']);
        // Don't look at this it's horrible :'( but this makes it think that there is 
        // something in user 
        $_GET['user'] = $_sub;
        // I dont know where you want it in the question its index.php and in comment 
        // its user.php so change this as you want it
        include 'user.php';
        // Exit so we dont have an user page and homepage together but only when
        // using user.php comment this out when using index.php
        exit;
    }
    // here is your standard index (sorry for the odd placing)
}else{
    //now here are we gonna play with the custom domain
    // this function should return the username if the hostname is found in the
    // database other wise it should return false
    $_user = userGetByDomain($_SERVER["HTTP_HOST"]);
    if($_user === false){
        // tell the browser its not legit
        header("Status: 404 Not Found");
        //show your 404 page
        include '404.php';
        // and die
        exit;
    }
    // now we know everything is okay we are gonna do the same thing as above
    $_GET['user'] = $_user;
    // I dont know where you want it in the question its index.php and in comment 
    // its user.php so change this as you want it
    include 'user.php';
    // Exit so we dont have an user page and homepage together but only when
    // using user.php comment this out when using index.php
    exit;
}

好的,我会修复它并给您一些PHP代码,因为这不是最容易的情况。 - EaterOfCode
嗨@EaterOfCorpses,我检查了我的服务器配置并发现我有这个预配置:*.mydomain.com. 14400 IN A 174.232.123.12 - 这不是CNAME,这会有影响吗? - Slay
当指向不同的 DNS 时,您需要使用 CNAME,但当您指向 IP 时,您需要使用 A 记录,因此,如果该 IP 是您的服务器主机,那应该没问题。顺便说一下,我已经得到了我的 cPanel 网站的凭据,所以今晚(如果我没有忘记)将会查看它。 - EaterOfCode
嗨@EateOfCorpses,我想问一下如果我不放置PHP代码会发生什么?这是必要的吗?我无法弄清楚那个PHP代码在哪里需要...(抱歉,我是初学者...努力学习中)。PHP代码用于什么? - Slay
如果您不使用PHP代码,它将显示该域的主页而不是SaaS应用程序,我认为您不希望出现这种情况,您也可以使用.htaccess文件并将其重定向到不同的文件夹,以满足您的需求 ;) - EaterOfCode
显示剩余7条评论

2

在客户端创建了CNAME之后,您需要让Apache知道要监听该CNAME。

因此,如果您的虚拟主机设置非常简单,如下所示:

<VirtualHost *:80>
    ServerName user.mysaasapp.com
    DocumentRoot /var/www/user
</VirtualHost>

您的客户的CNAME可能类似于以下内容:

customdomain.com        IN      CNAME  user.mysaasapp.com

您需要将customdomain.com添加到虚拟主机条目中,使其变为

<VirtualHost *:80>
    ServerName user.mysaasapp.com
    ServerAlias customdomain.com
    DocumentRoot /var/www/user
</VirtualHost>

我在这里做了一些假设,但这是我过去常用的方法,当然不包括任何打字错误。


你好,感谢回复。但是我没有名为 /var/www/user 的文件夹,我有一个 user.php 文件。 - Slay
@Slay,那只是示例代码,你应该根据自己的需求进行更改。 - Ivo

2
由于您希望处理站点中提供的任何主机名,因此您需要将站点放在主虚拟主机中(即在配置文件中第一次出现的虚拟主机)。主虚拟主机将处理所有未为其主机名定义特定虚拟主机的主机名请求。
在您的代码中,您应该检查 $_SERVER ['HTTP_HOST'] 并从中确定相关用户。您需要处理四种不同的情况:
1. 请求是针对您的主域(或 www.yourmaindomain )的,在这种情况下,您没有相关用户。 2. 请求是针对您的主域上的子域(例如 foouser.yourmaindomain ),则您知道请求是针对 foouser 的。 3. 请求不属于以上任何一种情况,但您已配置了一个用户以使用该主机名。您需要在代码中维护这些域到用户的分配,这超出了本问题的范围。 4. 请求不属于以上任何一种情况;某人错误地将主机名指向您的IP,或者指向了错误的主机名,或者尚未将主机名分配给用户,或者由于任何原因某人只是访问了您IP上的错误主机名。您需要为此情况显示某种未找到页面。
@ EaterOfCorpses的解决方案似乎假定您将能够确定用户的记录指向哪个主机名;这很少是真实的,并且很大程度上取决于用户的浏览器(即浏览器需要在HTTP请求中包含 Host:<CNAME target> 而不是 Host:<原始主机名> ,但浏览器提供了URL中使用的原始主机名,这仍将是用户的自定义域而不是由记录指向的 username.yourdomain )。

0

如果您的用户正在使用服务的默认端口,则无需担心任何事情。只需告诉您的用户在DNS管理器中更改CNAME(别名)和A(主机)设置即可。

@ --> 将指向DOMAIN_NAME(如果他们想要掩盖 theirdomain.com 到您的服务)。

saas --> 将指向user.mysaasapp.com(如果他们想要掩盖 saas.theirdomain.com 到您的服务)。

如果您允许他们使用特定端口使用您的特定服务,则可以将其添加到您的VirtualHost设置中。

<VirtualHost *:[[PORT_NUMBER]]>    // set to 80 if no special ports required.
ServerName mysaasapp.com
ServerAlias user.mysaasapp.com    // Change [[user]] to custom user's alias.
DocumentRoot USER_FOLDER 
</VirtualHost>

我希望这能解决你的问题。


嗨,USER_FOLDER 里我应该放什么?基本上没有用户文件夹。我正在为每个用户使用相同的文件夹-> 使用获取参数来识别为哪个用户显示什么内容,就像我在第一篇帖子中所述。 - Slay

0

假设您正在使用基于mod_rewrite的Apache httpd,您将使用以下httpd配置(来自http://httpd.apache.org/docs/2.2/vhosts/mass.html#simple):

一个简单的动态虚拟主机示例,适用于您的httpd.conf

# get the server name from the Host: header
UseCanonicalName Off

# this log format can be split per-virtual-host based on the first field
LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon
CustomLog logs/access_log vcommon

# include the server name in the filenames used to satisfy requests
VirtualDocumentRoot /www/hosts/%0/docs
VirtualScriptAlias /www/hosts/%0/cgi-bin

然后您需要将您的“saas应用程序”链接(无论是符号链接还是其他方式)到他们的CNAME“saas.theirdomain.com”,形成类似于此目录的形式:“/www/hosts/saas.theirdomain.com/docs”,基于上面的示例。
例如:
ln -s /www/mysaasapp/user /www/hosts/saas.theirdomain.com

/www/mysaasapp/user 是您的 SaaS 应用程序所在的位置。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接