Créez des sous-domaines à la volée avec .htaccess (PHP)

122

Je cherche à créer un système qui, lors de l'inscription, créera un sous-domaine sur mon site Web pour la zone de compte des utilisateurs.

par exemple johndoe.website.com

Je pense que ce serait quelque chose à voir avec le fichier .htaccess et éventuellement rediriger vers un autre emplacement sur le site Web? Je ne sais pas vraiment. Mais toute information pour commencer serait grandement appréciée.

La création d'une zone d'inscription n'est pas le problème - je l'ai fait plusieurs fois. Je ne sais pas par où commencer avec le sous-domaine.

Ben McRae
la source

Réponses:

125

Le rapide aperçu

  1. Vous devez créer un domaine générique sur votre serveur DNS * .website.com
  2. Ensuite, dans votre conteneur vhost, vous devrez également spécifier le caractère générique * .website.com - Ceci est fait dans les ServerAlias DOCs
  3. Ensuite, extrayez et vérifiez le sous-domaine en PHP et affichez les données appropriées

La version longue

1. Créez une entrée DNS générique

Dans vos paramètres DNS, vous devez créer une entrée de domaine générique telle que *.example.org. Une entrée générique ressemble à ceci:

*.example.org.   3600  A  127.0.0.1

2. Incluez le caractère générique dans vhost

Ensuite, dans la configuration Apache, vous devez configurer un conteneur vhost qui spécifie le caractère générique dans la directive ServerAlias DOCs . Un exemple de conteneur vhost:

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

3. Déterminez sur quel sous-domaine vous vous trouvez en PHP

Ensuite, dans vos scripts PHP, vous pouvez trouver le domaine en regardant dans la $_SERVERvariable super globale. Voici un exemple de capture du sous-domaine en PHP:

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

J'ai utilisé l'expression régulière ici pour permettre aux personnes d'accéder à votre site via www.subdomain.example.org ou subdomain.example.org.

Si vous ne prévoyez jamais avoir à traiter avec www. (ou d'autres sous-domaines) alors vous pouvez simplement utiliser une sous-chaîne comme ceci:

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

Hébergement virtuel de masse

L'hébergement virtuel de masse est un schéma légèrement différent de celui ci-dessus en ce sens que vous l'utiliseriez généralement pour héberger de nombreux sites Web distincts plutôt que d'essayer de l'utiliser pour alimenter une application comme le propose la question.

J'ai déjà documenté mon environnement d'hébergement virtuel de masse basé sur mod_rewrite dans un article sur mon blog , que vous pouvez consulter si c'est la route que vous souhaitez emprunter. Il y a aussi, bien sûr, la page de manuel Apache respective .

Apache a également un moyen interne de gérer l'hébergement virtuel de masse qui est légèrement moins flexible que la méthode mod_rewrite que j'ai utilisée. Tout cela est décrit sur la page de manuel de l'hébergement virtuel de masse Apache configuré dynamiquement .

Treffynnon
la source
À condition que vous puissiez utiliser wildcard subdomains, consultez ma solution pour le faire dans .htaccess.
Dan Bray
Je ne crois pas qu'un hôte virtuel puisse être ajouté à partir de .htaccess, cela me rend également nerveux au sujet de la sécurité. À partir de la version 2.4, il devrait être possible de sélectionner un répertoire de base dépendant du nom d'hôte (mais la méthode de Dan a également quelques problèmes) Considérez:RewriteRule "^/?(.*)" "http://%{HTTP_HOST}/%{HTTP_HOST}/$1" [L,R,NE]
symcbean
Notez que le code PHP implémentant ceci NE DOIT PAS fonctionner en tant qu'uid du serveur Web (devrait être en tant qu'utilisateur dédié via sudo)
symcbean
12

Vous pouvez autoriser chaque sous-domaine en premier lieu, puis vérifier si le sous-domaine est valide. Par exemple:

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

Dans le, index.phpvous pouvez extraire le sous-domaine en utilisant:

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

Mais tout cela nécessite que votre serveur Web accepte chaque nom de sous-domaine.

Gombo
la source
3
De plus, il faut que votre serveur DNS résout chaque nom de sous-domaine.
chaos
1
J'ai vu cela fait sur d'autres sites Web, ils n'ont sûrement pas à résoudre chaque sous-domaine à chaque fois?
Ben McRae
1
Eh bien, cela dépend de ce que vous entendez par là. Si vous voulez dire, chaque fois que quelqu'un sur Internet recherche foo.somedomain.com et qu'il n'est pas mis en cache, son serveur DNS doit le résoudre, alors oui.
chaos
Si vous voulez dire, doivent-ils configurer des enregistrements DNS spécifiquement pour chaque domaine, voir la réponse de Treffynnon.
chaos
ok merci pour ça. Je ne comprends pas très bien ce que Treffynnon signifie en spécifiant le caractère générique dans le vhost?
Ben McRae
6

J'ai trouvé plus facile de le faire avec PHP. En fait, c'est créer un sous-domaine dans cPanel et créer votre dossier sous le nom de domaine souhaité. Comme vous le ferez manuellement dans cPanel mais tout est fait en millisecondes par une simple fonction PHP. Aucun clic nécessaire :)

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.
la source
Vérifiez s'il a été créé avec succès sur cPanel et, vérifiez par FTP (ou gestionnaire de fichiers), ce qu'il y a à l'intérieur du dossier public_html / subdomain. Si vous avez un paramètre cPanel ajoutant des éléments lorsque vous créez un sous-domaine, cela n'est pas lié à la création de sous-domaines à la volée.
Adrian P.
Non n'a pas été créé dans cPanel
Ruchi
Alors vous n'avez pas assez de permission sur cPanel. S'agit-il d'un VPS d'hébergement partagé ou d'un serveur dédié?
Adrian P.
Il peut y avoir plusieurs raisons pour ne pas créer le sous-domaine. Non lié au script ci-dessus mais à votre configuration DNS. Lisez cela et demandez de l'aide sur les forums cPanel. forums.cpanel.net/threads/subdomains-not-working.228132
Adrian P.
5

Le moyen le plus simple est de rediriger tous les sous-domaines (avec un caractère générique *) pour qu'ils pointent vers votre / wwwroot. Ensuite, placez .htaccess dans ce dossier avec le code suivant:

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]

Cela permettra à chaque sous-dossier du dossier / wwwroot d'être acceptable via le sous-domaine (nomdossier.domaine.com).

Trouvé il y a des années sur http://www.webmasterworld.com/apache/3163397.htm

Glavić
la source
4

Cela n'a rien à voir avec .htaccess. Vous devrez configurer des enregistrements DNS et un hébergement virtuel pour les sous-domaines.

le chaos
la source
4

Mod_vhost_alias est le bon module pour cela.

Avec une ligne, vous pouvez dire à Apache de regarder au bon endroit, avec le hachage de répertoire, etc. Par exemple, la ligne:

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

dirait à Apache de définir la racine du document sur / http / users / s / u / sous-domaine lorsque cela est demandé pour sous-domaine.votredomaine.com

Julien Tartarin
la source
0

Je pense que le DNS générique avec l'hébergement virtuel de masse dynamique d'Apache est également une solution raisonnable. Bien que je ne l'ai jamais essayé.

Si vous avez besoin de passer à plusieurs serveurs ou que les autres solutions ne fonctionnent tout simplement pas pour vous, je vous recommande d'utiliser un serveur DNS basé sur une base de données. J'ai utilisé avec succès MyDNS dans le passé. Puisqu'il utilise MySQL (ou PostgreSQL), vous pouvez mettre à jour votre DNS à la volée avec PHP ou à peu près n'importe quoi d'autre. Le code ne semble pas avoir été mis à jour depuis un certain temps, mais c'est du DNS et donc pas exactement de pointe.

Barrett Conrad
la source
0

Méthodes de création de sous-domaine Wildcard

Vous devez d'abord créer les paramètres DNS à l'aide de l'éditeur DNS de votre serveur.

  1. Créez un Aenregistrement dans les paramètres DNS avec *un joker d'hôte dans l'adresse IP du serveur.

    * 1400 IN A ip_address

  2. Créez à nouveau un Aenregistrement dans les paramètres DNS avec l'hôte @ou domain_name.tlddans l'adresse IP du serveur. tld signifie les domaines de premier niveau ou l'extension des domaines tels que .com, .org, etc ....

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

  3. Créez un CNAMEenregistrement comme:

    www 1400 IN A domainname.tld

  4. Créez le sous-domaine avec un *caractère générique comme*.domain.tld
  5. Créez htaccess dans votre répertoire de sous-domaine *.domain.tldet mettez ce code:

    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

    Testez votre premier sous-domaine générique comme example.domainname.tld

Si vous n'êtes pas intéressé à passer les données en tant que paramètre à l'aide du htaccess, vous pouvez également obtenir les données en utilisant le codage suivant:

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

et utilisez votre variable globale à n'importe quel endroit comme global $get_data.

echo $get_data->data; //example

(note: Cette classe est principalement utilisée pour obtenir le sous-domaine exact à partir de http_host. parce que certains noms supplémentaires combinés avant votre sous-domaine sont également applicables comme www.example.domainname.tld. Ce retour $_GET['data']='wwww'Donc, ma suggestion est d'utiliser $_SERVER['http_host']pour obtenir les valeurs exactes au lieu d'utiliser les $_SERVER['query_string']paramètres htaccess ou passés dans votre page d'index)

6. Accélérez l'exécution de ce sous-domaine générique utilise N secondes dans TTL - PARAMÈTRES DNS.

7.Vérifiez le sous-domaine après votre temps ttl donné (600-10 minutes) comme => http://abc.domain.tld

(Remarque: les sous-domaines génériques ne remplacent pas les sous-domaines existants. Parce que la première priorité est toujours pour vos sous-domaines existants)

karthikeyan ganesan
la source