Crie subdomínios em tempo real com .htaccess (PHP)

122

Estou procurando criar um sistema que, ao se inscrever, crie um subdomínio no meu site para a área de conta dos usuários.

por exemplo, johndoe.website.com

Eu acho que seria algo a ver com o arquivo .htaccess e, possivelmente, redirecionar para outro local no site? Na verdade eu não sei. Mas qualquer informação para começar seria muito apreciada.

Criar uma área de inscrição não é o problema - já fiz isso várias vezes. Não sei por onde começar com o subdomínio.

Ben McRae
fonte

Respostas:

125

O rápido resumo

  1. Você precisa criar um domínio curinga no seu servidor DNS * .website.com
  2. Em seguida, no seu contêiner vhost, você também precisará especificar o curinga * .website.com - Isso é feito nos ServerAlias DOCs
  3. Em seguida, extraia e verifique o subdomínio no PHP e exiba os dados apropriados

A versão longa

1. Crie uma entrada DNS curinga

Nas configurações de DNS, você precisa criar uma entrada de domínio curinga , como *.example.org. Uma entrada curinga é assim:

*.example.org.   3600  A  127.0.0.1

2. Inclua o curinga no vhost

Em seguida, na configuração do Apache, é necessário definir um contêiner vhost que especifique o curinga na diretiva ServerAlias DOCs . Um exemplo de contêiner vhost:

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

3. Descubra em qual subdomínio você está no PHP

Em seus scripts PHP, você pode descobrir o domínio procurando na $_SERVERvariável super global. Aqui está um exemplo de como pegar o subdomínio no PHP:

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

Usei o regex aqui para permitir que as pessoas acessem seu site via www.subdomain.example.org ou subdomain.example.org.

Se você nunca espera ter que lidar com www. (ou outros subdomínios), você pode simplesmente usar uma substring da seguinte forma:

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

Hospedagem virtual em massa

A hospedagem virtual em massa é um esquema ligeiramente diferente do anterior, pois você costuma usá-lo para hospedar muitos sites distintos, em vez de tentar usá-lo em um aplicativo, conforme a pergunta.

Documentei meu ambiente de hospedagem virtual em massa com base em mod_rewrite antes em uma postagem no meu blog , que você pode ver se é esse o caminho que deseja seguir. Também existe, é claro, a respectiva página de manual do Apache .

O Apache também possui uma maneira interna de lidar com hospedagem virtual em massa que é um pouco menos flexível que o método mod_rewrite que eu usei. Tudo isso é descrito na página de manual do Apache Dynamic Hosting em massa, configurada dinamicamente .

Treffynnon
fonte
Desde que você possa usar wildcard subdomains, consulte minha solução para fazer isso .htaccess.
Dan Bray
Não acredito que um host virtual possa ser adicionado a partir do .htaccess, mas também me deixa nervoso com a segurança. A partir da 2.4, deve ser possível selecionar um diretório base dependente do nome do host (mas o método de Dan também tem alguns problemas) Considere:RewriteRule "^/?(.*)" "http://%{HTTP_HOST}/%{HTTP_HOST}/$1" [L,R,NE]
symcbean
Note que o código PHP implementar este não deve ser executado como o uid servidor web (deve ser como um usuário dedicado via sudo)
symcbean
12

Você pode permitir todos os subdomínios em primeiro lugar e depois verificar se o subdomínio é válido. Por exemplo:

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

Dentro do que index.phpvocê pode extrair o subdomínio usando:

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

Mas tudo isso requer que seu servidor da web aceite todos os nomes de subdomínios.

quiabo
fonte
3
Além disso, exige que o servidor DNS resolva todos os nomes de subdomínios.
caos
1
Eu já vi isso feito em outros sites, certamente eles não precisam resolver todos os subdomínios toda vez que fazem?
25711 Ben McRae
1
Bem, depende do que você quer dizer com isso. Se você quer dizer, toda vez que alguém na internet consulta foo.somedomain.com e ele não é armazenado em cache, o servidor DNS precisa resolvê-lo.
caos
Se você quer dizer que eles precisam configurar registros DNS especificamente para cada domínio, consulte a resposta de Treffynnon.
caos
ok obrigado por isso. Eu não entendo o que Treffynnon significa especificando o curinga no vhost?
21909 Ben McRae
6

Achei mais fácil fazê-lo com PHP. De fato, está criando um subdomínio no cPanel e crie sua pasta com o nome de domínio desejado. Como você faz manualmente no cPanel, mas tudo é feito em milissegundos por uma simples função PHP. Não é necessário clicar :)

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";

}
Adrian P.
fonte
Verifique se ele foi criado com sucesso no cPanel e, por FTP (ou gerenciador de arquivos), o que há dentro da pasta public_html / subdomínio. Se você tiver uma configuração do cPanel adicionando itens ao criar um subdomínio, isso não está relacionado à criação de subdomínios em tempo real.
Adrian P.
Não foi criado no cPanel
Ruchi
Então você não tem permissão suficiente no cPanel. Este é um VPS de hospedagem compartilhada ou servidor dedicado?
Adrian P.
Pode haver vários motivos para não criar o subdomínio. Não está relacionado ao script acima, mas com a sua configuração de DNS. Leia isso e peça ajuda nos fóruns do cPanel. forums.cpanel.net/threads/subdomains-not-working.228132
Adrian P.
5

A maneira mais fácil é redirecionar todos os subdomínios (com curinga *) para apontar para o seu / wwwroot. Em seguida, coloque .htaccess nesta pasta com o seguinte código:

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]

Isso fará com que todas as subpastas da pasta / wwwroot sejam aceitáveis ​​via subdomínio (nome_do_domínio.domínio.com).

Encontrado este ano atrás em http://www.webmasterworld.com/apache/3163397.htm

Glavić
fonte
4

Não tem nada a ver com .htaccess. Você precisará configurar registros DNS e hospedagem virtual para os subdomínios.

caos
fonte
4

Mod_vhost_alias é o módulo certo para fazer isso.

Com uma linha, você pode dizer ao Apache para procurar o lugar certo, com hash de diretório, etc. Por exemplo, a linha:

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

diria ao Apache para definir a raiz do documento como / http / users / s / u / subdomínio quando solicitado para subdomínio.seudominio.com

Julien Tartarin
fonte
0

Eu acho que o DNS do curinga com o Dynamic Mass Virtual Hosting da Apache também é uma solução razoável. Embora, eu nunca tentei.

Se você precisar expandir para vários servidores ou outras soluções simplesmente não funcionarem, recomendo usar um servidor DNS orientado a banco de dados. Eu usei o MyDNS com sucesso no passado. Como ele usa MySQL (ou PostgreSQL), você pode atualizar seu DNS rapidamente com PHP ou qualquer outra coisa. O código não parece ter sido atualizado há algum tempo, mas é DNS e, portanto, não é exatamente de ponta.

Barrett Conrad
fonte
0

Métodos de criação de subdomínio curinga

Primeiro, você precisa criar as configurações de DNS usando o editor de DNS do servidor.

  1. Crie um Aregistro nas configurações de DNS com o *curinga do host no endereço IP do servidor.

    * 1400 IN A ip_address

  2. Crie mais uma vez um Aregistro nas configurações de DNS com o host @ou domain_name.tldno endereço IP do servidor. tld significa domínios de nível superior ou a extensão de domínios como .com, .org, etc.

    @ 1400 IN A ip_address ou domain_name.tld 1400 IN A ip_address

  3. Crie um CNAMEregistro como:

    www 1400 IN A domainname.tld

  4. Crie o subdomínio com *curinga como*.domain.tld
  5. Crie o htaccess no diretório do seu subdomínio *.domain.tlde coloque este código:

    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

    Teste seu primeiro subdomínio curinga como example.domainname.tld

Se você não tiver interesse em passar os dados como parâmetro usando o htaccess, também poderá obter os dados usando a seguinte codificação:

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();

e use sua variável global em qualquer lugar como global $get_data.

echo $get_data->data; //example

(note: Essa classe é usada principalmente para obter o nome do subdomínio exato de http_host., porque alguns nomes extras combinados antes do seu subdomínio também são aplicáveis, como www.example.domainname.tld. Este retorno $_GET['data']='wwww'Então, minha sugestão é usar o $_SERVER['http_host']para obter os valores exatos em vez de usar o$_SERVER['query_string'] parâmetros ou passados ​​htaccess em sua página de índice)

6.A acelerar a execução desses subdomínios curinga, use N segundos em TTL - DNS SETTINGS.

7. Verifique o subdomínio após o tempo ttl (600 a 10 minutos), como => http://abc.domain.tld

(observação: os subdomínios curinga não substituem os subdomínios existentes. Como a primeira prioridade sempre para os subdomínios existentes)

karthikeyan ganesan
fonte