【问题标题】:Create subdomains on the fly with .htaccess (PHP)使用 .htaccess (PHP) 即时创建子域
【发布时间】:2010-10-09 19:47:46
【问题描述】:

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

例如johndoe.website.com

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

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

【问题讨论】:

    标签: php .htaccess dns virtualhost subdomain


    【解决方案1】:

    简要介绍

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

    长版

    1。创建通配符 DNS 条目

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

    *.example.org.   3600  A  127.0.0.1
    

    2。在 vhost 中包含通配符

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

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

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

    然后在您的 PHP 脚本中,您可以通过查看 $_SERVER 超级全局变量来找出域。下面是一个在 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'], '.')
                 );
    

    海量虚拟主机

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

    我之前在post on my blog 中记录了我的基于 mod_rewrite 的大规模虚拟主机环境,如果这是您希望采用的方法,您可以查看它。当然还有respective Apache manual page

    Apache 还有一种处理海量虚拟主机的内部方法,它的灵活性比我使用的 mod_rewrite 方法稍差。这在 Apache Dynamically Configured Mass Virtual Hosting manual page 上都有描述。

    【讨论】:

    • 如果您可以使用wildcard subdomains,请在.htaccess 中查看我的解决方案。
    • 我不相信可以从 .htaccess 添加虚拟主机,这也让我对安全性感到紧张。从 2.4 开始,应该可以根据主机名选择一个基本目录(但 Dan 的方法也有一些问题)考虑:RewriteRule "^/?(.*)" "http://%{HTTP_HOST}/%{HTTP_HOST}/$1" [L,R,NE]
    • 请注意,实现此功能的 PHP 代码不得作为网络服务器 uid 运行(应通过 sudo 以专用用户身份运行)
    【解决方案2】:

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

    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]);
    }
    

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

    【讨论】:

    • 此外,它要求您的 DNS 服务器解析每个子域名。
    • 我在其他网站上看到过这种做法,他们肯定不必每次都解析每个子域吗?
    • 嗯,这取决于你的意思。如果你的意思是,每次互联网上有人查找 foo.somedomain.com 并且它没有被缓存时,他们的 DNS 服务器必须解析它,那么是的。
    • 如果您的意思是,他们是否必须专门为每个域设置 DNS 记录,请参阅 Treffynnon 的回答。
    • 好的,谢谢。我不太明白 Treffynnon 在虚拟主机中指定通配符是什么意思?
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      最简单的方法是将所有子域(使用通配符 *)重定向到您的 /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]
      

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

      发现于几年前 http://www.webmasterworld.com/apache/3163397.htm

      【讨论】:

        【解决方案5】:

        我发现使用 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";
        
        }
        

        【讨论】:

        • 检查它是否在 cPanel 上成功创建,并通过 FTP(或文件管理器)检查 public_html/subdomain 文件夹内的内容。如果您在创建子域时有一个 cPanel 设置添加内容,这与动态创建子域无关。
        • 没有在cPanel中没有创建
        • 那你没有足够的cPanel权限。这是共享主机 VPS 还是专用服务器?
        • 不创建子域可能有多种原因。与上面的脚本无关,但与您的 DNS 配置有关。阅读并在 cPanel 论坛上寻求帮助。 forums.cpanel.net/threads/subdomains-not-working.228132
        【解决方案6】:

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

        【讨论】:

          【解决方案7】:

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

          通过一行代码,您可以告诉 Apache 查看正确的位置,使用目录散列等。 例如,该行:

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

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

          【讨论】:

            【解决方案8】:

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

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

            【讨论】:

              【解决方案9】:

              通配符子域创建方法

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

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

                * 1400 IN A ip_address

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

                @ 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. *.domain.tld 的子域目录中创建 htaccess 并输入以下代码:

                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'所以我的建议是使用@987654342 @ 用于获取确切的值,而不是使用 $_SERVER['query_string'] 或在索引页面中传递 htaccess 参数)

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

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

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

              【讨论】:

                猜你喜欢
                • 2011-01-12
                • 2011-10-28
                • 2021-09-01
                • 1970-01-01
                • 2014-07-02
                • 2023-03-14
                • 2016-04-14
                • 2012-07-11
                相关资源
                最近更新 更多