Создавайте поддомены на лету с помощью .htaccess (PHP)

122

Я хочу создать систему, которая при регистрации создаст поддомен на моем веб-сайте для области учетной записи пользователя.

например, johndoe.website.com

Я думаю, это как-то связано с файлом .htaccess и, возможно, перенаправлением в другое место на веб-сайте? На самом деле я не знаю. Но я был бы очень признателен за любую информацию для начала.

Создать зону регистрации - не проблема - я делал это много раз. Я просто не уверен, с чего начать с поддомена.

Бен Макрей
источник

Ответы:

125

Краткое изложение

  1. Вам необходимо создать домен с подстановочными знаками на вашем DNS-сервере * .website.com
  2. Затем в вашем контейнере vhost вам нужно будет также указать подстановочный знак * .website.com - это делается в ServerAlias DOC
  3. Затем извлеките и проверьте субдомен в PHP и отобразите соответствующие данные.

Длинная версия

1. Создайте запись DNS с подстановочными знаками.

В настройках DNS вам необходимо создать запись домена с подстановочными знаками, например *.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'], '.')
             );

Массовый виртуальный хостинг

Массовый виртуальный хостинг - это схема, немного отличающаяся от приведенной выше, поскольку вы обычно используете его для размещения множества различных веб-сайтов, а не пытаетесь использовать его для работы приложения, как предлагает вопрос.

Я задокументировал свою среду массового виртуального хостинга на основе mod_rewrite ранее в сообщении в моем блоге , и вы могли бы посмотреть на него, если хотите пойти по этому пути. Также, конечно же, есть соответствующая страница руководства Apache .

У Apache также есть внутренний способ работы с массовым виртуальным хостингом, который немного менее гибкий, чем метод mod_rewrite, который я использовал. Все это описано на странице руководства Apache Dynamically Configured Mass Virtual Hosting .

Treffynnon
источник
При условии, что вы можете использовать wildcard subdomains, см. Мое решение для этого в .htaccess.
Дэн Брэй,
Я не верю, что виртуальный хост может быть добавлен из .htaccess, это также заставляет меня нервничать по поводу безопасности. Начиная с версии 2.4, должна быть возможность выбрать базовый каталог в зависимости от имени хоста (но у метода Дэна тоже есть некоторые проблемы). Учтите:RewriteRule "^/?(.*)" "http://%{HTTP_HOST}/%{HTTP_HOST}/$1" [L,R,NE]
symcbean
Обратите внимание, что код PHP, реализующий это, НЕ ДОЛЖЕН запускаться как uid веб-сервера (должен быть выделенным пользователем через sudo)
symcbean
12

Вы можете сначала разрешить каждый субдомен, а затем проверить, действителен ли субдомен. Например:

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

Но все это требует, чтобы ваш веб-сервер принимал каждое имя поддомена.

гумбо
источник
3
Более того, для этого требуется, чтобы ваш DNS-сервер разрешал каждое имя поддомена.
хаос
1
Я видел, как это делалось на других веб-сайтах, ведь им не обязательно каждый раз разрешать каждый субдомен?
Ben McRae
1
Ну, это зависит от того, что вы имеете в виду. Если вы имеете в виду, что каждый раз, когда кто-то в Интернете ищет foo.somedomain.com, а он не кэширован, его DNS-сервер должен разрешить его, тогда да.
хаос
Если вы имеете в виду, нужно ли им настраивать записи DNS специально для каждого домена, см. Ответ Треффиннона.
хаос
хорошо, спасибо за это. я не совсем понимаю, что Treffynnon имеет в виду, указав подстановочный знак в vhost?
Ben McRae
7

В дополнение к настройке подстановочного знака DNS вы можете взглянуть на Dynamic Mass Virtual Hosting для Apache, и именно так я решил эту проблему в прошлом.

Роуленд Шоу
источник
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";

}
Адриан П.
источник
Проверьте, успешно ли он был создан на cPanel, и проверьте с помощью FTP (или файлового менеджера), что находится внутри папки public_html / subdomain. Если у вас есть настройка cPanel, добавляющая данные при создании субдомена, это не связано с созданием субдоменов на лету.
Адриан П.
Нет не был создан в Cpanel
Ручьи
Тогда у вас недостаточно разрешений на cPanel. Это виртуальный хостинг VPS или выделенный сервер?
Адриан П.
Причин отказа от создания субдомена может быть несколько. Не связано с приведенным выше сценарием, но с вашей конфигурацией DNS. Прочтите это и попросите помощи на форумах cPanel. форумы.cpanel.net/threads/subdomains-not-working.228132
Адриан П.
5

Самый простой способ - перенаправить все поддомены (с подстановочным знаком *), чтобы они указывали на ваш / 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 будет доступна через поддомен (имя_папки.domain.com).

Найдено несколько лет назад на http://www.webmasterworld.com/apache/3163397.htm

Glavic
источник
4

Это не имеет отношения к .htaccess. Вам необходимо настроить записи DNS и виртуальный хостинг для поддоменов.

хаос
источник
4

Mod_vhost_alias - правильный модуль для этого.

С помощью одной строки вы можете указать Apache, чтобы он смотрел в нужное место, с хешированием каталогов и т. Д. Например, строка:

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

сообщит Apache установить корень документа в / http / users / s / u / subdomain при запросе для subdomain.yourdomain.com

Жюльен Тартарен
источник
0

Я думаю, что альтернативный DNS с динамическим массовым виртуальным хостингом Apache также является разумным решением. Хотя, никогда не пробовал.

Если вам необходимо масштабировать до нескольких серверов или другие решения просто не работают для вас, я рекомендую использовать DNS-сервер, управляемый базой данных. Раньше я успешно использовал MyDNS . Поскольку он использует MySQL (или PostgreSQL), вы можете обновлять свой DNS «на лету» с помощью PHP или чего-то еще. Код не выглядит так, как будто он обновлялся какое-то время, но это DNS и, следовательно, не совсем ультрасовременный.

Барретт Конрад
источник
0

Методы создания поддоменов с подстановочными знаками

Во-первых, вам необходимо создать настройки DNS с помощью редактора DNS вашего сервера.

  1. Создайте Aзапись в настройках DNS с подстановочным *знаком хоста в IP-адресе сервера.

    * 1400 IN A ip_address

  2. Создайте еще раз Aзапись в настройках DNS с хостом @или domain_name.tldIP-адресом сервера. 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. Создайте 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']для получения точных значений вместо использования $_SERVER['query_string']или переданных параметров htaccess в ваша индексная страница)

6. Ускорьте выполнение этого поддомена с подстановочными знаками, используя N секунд в TTL - НАСТРОЙКИ DNS.

7.Проверьте субдомен после заданного времени ttl (600-10 минут), например => http://abc.domain.tld

(примечание: поддомены с подстановочными знаками не отменяют существующие поддомены. Поскольку первый приоритет всегда для ваших существующих поддоменов)

Картикеян Ганесан
источник