125

我正在寻找一个系统,在注册时将在我的网站上为用户帐户区域创建一个子域。

例如 johndoe.website.com

我认为这与 .htaccess 文件有关,并可能重定向到网站上的另一个位置?我其实不知道。但任何让我开始的信息将不胜感激。

创建一个注册区不是问题——我已经做过很多次了。我只是不确定从哪里开始子域。

4

9 回答 9

126

快速概述

  1. 您需要在您的 DNS 服务器 *.website.com 上创建一个通配符域
  2. 然后在您的虚拟主机容器中,您还需要指定通配符 *.website.com - 这是在文档中完成ServerAlias
  3. 然后在PHP中提取并验证子域并显示相应的数据

长版

1.创建通配符DNS条目

在您的 DNS 设置中,您需要创建一个通配符域条目,例如*.example.org. 通配符条目如下所示:

*.example.org.   3600  A  127.0.0.1

2.在vhost中包含通配符

接下来在 Apache 配置中,您需要设置一个在ServerAlias DOCs指令中指定通配符的 vhost 容器。一个示例虚拟主机容器:

<VirtualHost *:80>
  ServerName server.example.org
  ServerAlias *.example.org
  UseCanonicalName Off
</VirtualHost>

3. 在 PHP 中找出您所在的子域

$_SERVER然后在您的 PHP 脚本中,您可以通过查看超级全局变量来找出域。下面是一个在 PHP 中抓取子域的例子:

preg_match('/([^.]+)\.example\.org/', $_SERVER['SERVER_NAME'], $matches);
if(isset($matches[1])) {
    $subdomain = $matches[1];
}

我在这里使用了正则表达式来允许人们通过 www.subdomain.example.org 或 subdomain.example.org 访问您的网站。

如果您从未预料到必须处理 www. (或其他子域)然后你可以简单地使用这样的子字符串:

$subdomain = substr(
                 $_SERVER['SERVER_NAME'], 0,
                 strpos($_SERVER['SERVER_NAME'], '.')
             );

海量虚拟主机

大规模虚拟主机与上述方案略有不同,因为您通常会使用它来托管许多不同的网站,而不是像问题提出的那样尝试使用它来为应用程序提供动力。

我之前在我的博客上的一篇文章中记录了我的基于 mod_rewrite 的大规模虚拟主机环境,你可以看看这是否是你希望采取的路线。当然,还有相应的 Apache 手册页

Apache 还有一种处理海量虚拟主机的内部方法,它的灵活性比我使用的 mod_rewrite 方法稍差。这一切都在 Apache动态配置的大规模虚拟主机手册页中进行了描述。

于 2009-02-25T14:21:06.967 回答
13

您可以首先允许每个子域,然后检查子域是否有效。例如:

RewriteEngine on
RewriteCond %{HTTP_HOST} ^[^.]+\.example\.com$
RewriteRule !^index\.php$ index.php [L]

在内部,index.php您可以使用以下方法提取子域:

if (preg_match('/^([^.]+)\.example\.com$/', $_SERVER['HTTP_HOST'], $match)) {
    var_dump($match[1]);
}

但这一切都要求您的网络服务器接受每个子域名。

于 2009-02-25T14:18:16.397 回答
7

除了设置 DNS 通配符之外,您可能还想看看Dynamic Mass Virtual Hosting for Apache这是我过去解决这个问题的方法

于 2009-02-25T14:38:43.053 回答
6

最简单的方法是将所有子域(使用通配符 *)重定向到您的 /wwwroot。然后使用以下代码将 .htaccess 放入此文件夹:

RewriteCond %{ENV:REDIRECT_SUBDOMAIN} ="" 
RewriteCond %{HTTP_HOST} ^([a-z0-9][-a-z0-9]+)\.domain\.com\.?(:80)?$ [NC] 
RewriteCond %{DOCUMENT_ROOT}/%1 -d 
RewriteRule ^(.*) %1/$1 [E=SUBDOMAIN:%1,L] 
RewriteRule ^ - [E=SUBDOMAIN:%{ENV:REDIRECT_SUBDOMAIN},L]

这将通过子域 (foldername.domain.com) 实现 /wwwroot 文件夹的每个子文件夹。

几年前在 http://www.webmasterworld.com/apache/3163397.htm上发现的

于 2009-02-25T15:55:47.987 回答
6

我发现用 PHP 做起来更容易。实际上是在 cPanel 中创建一个子域,并在所需的域名下创建您的文件夹。正如您将在 cPanel 中手动完成的那样,但所有这些都是通过一个简单的 PHP 函数在几毫秒内完成的。无需点击 :)

function create_subdomain($subDomain,$cPanelUser,$cPanelPass,$rootDomain) {

    //  $buildRequest = "/frontend/x3/subdomain/doadddomain.html?rootdomain=" . $rootDomain . "&domain=" . $subDomain;

    $buildRequest = "/frontend/x3/subdomain/doadddomain.html?rootdomain=" . $rootDomain . "&domain=" . $subDomain . "&dir=public_html/subdomains/" . $subDomain;

    $openSocket = fsockopen('localhost',2082);
    if(!$openSocket) {
        return "Socket error";
        exit();
    }

    $authString = $cPanelUser . ":" . $cPanelPass;
    $authPass = base64_encode($authString);
    $buildHeaders  = "GET " . $buildRequest ."\r\n";
    $buildHeaders .= "HTTP/1.0\r\n";
    $buildHeaders .= "Host:localhost\r\n";
    $buildHeaders .= "Authorization: Basic " . $authPass . "\r\n";
    $buildHeaders .= "\r\n";

    fputs($openSocket, $buildHeaders);
        while(!feof($openSocket)) {
           fgets($openSocket,128);
        }
    fclose($openSocket);

    $newDomain = "http://" . $subDomain . "." . $rootDomain . "/";

   //  return "Created subdomain $newDomain";

}
于 2013-02-13T01:55:50.403 回答
4

这与.htaccess 无关。您需要为子域设置 DNS 记录和虚拟主机。

于 2009-02-25T14:17:23.807 回答
4

Mod_vhost_alias是执行此操作的正确模块。

只需一行,您就可以告诉 Apache 使用目录散列等方法查看正确的位置。例如,以下行:

VirtualDocumentRoot /http/users/%3.1/%3.2/%3

当请求 subdomain.yourdomain.com 时,会告诉 Apache 将文档根设置为 /http/users/s/u/subdomain

于 2009-04-14T11:20:22.320 回答
0

我认为带有 Apache 的动态海量虚拟主机的通配符 DNS 也是一个合理的解决方案。虽然,我从未尝试过。

如果您需要扩展到多台服务器或其他解决方案不适合您,我建议使用数据库驱动的 DNS 服务器。我过去曾成功使用过 MyDNS。由于它使用 MySQL(或 PostgreSQL),因此您可以使用 PHP 或其他任何方式即时更新您的 DNS。该代码看起来好像已经有一段时间没有更新了,但它是 DNS,因此并不完全是最先进的。

于 2009-02-25T15:13:18.010 回答
0

通配符子域创建方法

首先,您必须使用服务器 DNS 编辑器创建 DNS 设置。

  1. 在服务器 IP 地址中使用主机通配符A在 DNS 设置中创建记录。*

    * 1400 IN A ip_address

  2. 使用主机或服务器 IP 地址A在 DNS 设置中再次创建记录。tld 表示顶级域或.com、.org 等域的扩展......@domain_name.tld

    @ 1400 IN A ip_address 或者 domain_name.tld 1400 IN A ip_address

  3. 创建CNAME记录,如:

    www 1400 IN A domainname.tld

  4. *使用通配符创建子域,例如*.domain.tld
  5. 在您的子域目录中创建 htaccess*.domain.tld并输入以下代码:

    Options +FollowSymLinks 
    RewriteEngine On 
    RewriteBase /
    RewriteRule ^([aA-zZ0-9]+)$ index.php?data=$1
    RewriteCond %{HTTP_HOST} ^([aA-zZ0-9]+)\.([aA-zZ0-9-]+)\.([aA-zZ]+)
    RewriteRule ([aA-zZ0-9]+) index.php?data=%1
    

    测试您的第一个通配符子域,例如example.domainname.tld

如果您不想使用 htaccess 将数据作为参数传递,您也可以使用以下编码获取数据:

define("SUBDOMAIN_PARENT","domainname.tld");   
class getData
    {
         function __construct()
        {
            $this->data="";
            $http_host=$_SERVER['HTTP_HOST'];
         $subdom_data= str_replace(SUBDOMAIN_PARENT,"",$http_host);
         $expl_subdom_data=explode(".",$subdom_data);
      $expl_subdom_data=array_filter($expl_subdom_data);

            if($expl_subdom_data!=NULL)
            {
           $this->data=end($expl_subdom_data);
            }
       }
    }
$GLOBALS['get_data']=new getData();

并在任何地方使用您的全局变量,例如global $get_data.

echo $get_data->data; //example

(注意:此类主要用于从http_host. 获取确切的子域名,因为在您的子域之前组合的一些额外名称也适用于www.example.domainname.tld. 此返回$_GET['data']='wwww'所以我的建议是使用$_SERVER['http_host']for 获取确切的值,而不是$_SERVER['query_string']使用您的索引页)

6.加速这个通配符子域的执行,在 TTL - DNS SETTINGS 中使用 N 秒。

7.在给定的 ttl 时间(600 - 10 分钟)后检查子域,例如 =>http://abc.domain.tld

(注意:通配符子域不会覆盖现有的子域。因为您现有的子域始终是第一优先级)

于 2017-06-02T10:22:38.433 回答