Twórz subdomeny w locie dzięki .htaccess (PHP)

122

Chcę stworzyć system, który po rejestracji utworzy subdomenę w mojej witrynie dla obszaru konta użytkowników.

np. johndoe.website.com

Myślę, że miałoby to coś wspólnego z plikiem .htaccess i prawdopodobnie przekierowaniem do innej lokalizacji w witrynie? Właściwie nie wiem. Ale wszelkie informacje, które mogłyby mi pomóc, byłyby bardzo mile widziane.

Utworzenie obszaru rejestracji nie jest problemem - robiłem to niejednokrotnie. Po prostu nie jestem pewien, od czego zacząć od subdomeny.

Ben McRae
źródło

Odpowiedzi:

125

Szybki przegląd

  1. Musisz utworzyć domenę z symbolem wieloznacznym na swoim serwerze DNS * .website.com
  2. Następnie w kontenerze vhost musisz również określić symbol wieloznaczny * .website.com - odbywa się to w ServerAlias DOC
  3. Następnie wyodrębnij i zweryfikuj subdomenę w PHP i wyświetl odpowiednie dane

Wersja długa

1. Utwórz wpis DNS z symbolem wieloznacznym

W ustawieniach DNS musisz utworzyć wpis domeny z symbolem wieloznacznym, taki jak *.example.org. Wpis z symbolem wieloznacznym wygląda następująco:

*.example.org.   3600  A  127.0.0.1

2. Dołącz symbol wieloznaczny do vhost

Następnie w konfiguracji Apache musisz ustawić kontener vhost, który określa symbol wieloznaczny w dyrektywie ServerAlias DOCs . Przykładowy kontener vhost:

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

3. Sprawdź, na której subdomenie jesteś w PHP

Następnie w skryptach PHP możesz znaleźć domenę, patrząc w $_SERVERsuper globalnej zmiennej. Oto przykład przechwycenia subdomeny w PHP:

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

Użyłem tutaj wyrażenia regularnego, aby umożliwić ludziom odwiedzanie Twojej witryny za pośrednictwem www.subdomain.example.org lub subdomain.example.org.

Jeśli nigdy nie spodziewasz się, że będziesz mieć do czynienia z www. (lub inne subdomeny), możesz po prostu użyć podciągu w ten sposób:

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

Masowy hosting wirtualny

Masowy hosting wirtualny to nieco inny schemat niż powyższy, ponieważ zwykle używasz go do hostowania wielu różnych witryn internetowych, zamiast próbować używać go do zasilania aplikacji, jak sugeruje pytanie.

Moje środowisko wirtualnego hostingu masowego, oparte na mod_rewrite, udokumentowałem wcześniej w poście na moim blogu , do którego możesz się przyjrzeć, jeśli jest to droga, którą chcesz wybrać. Istnieje również oczywiście odpowiednia strona podręcznika Apache .

Apache ma również wewnętrzny sposób radzenia sobie z masowym wirtualnym hostingiem, który jest nieco mniej elastyczny niż metoda mod_rewrite, której użyłem. Wszystko to jest opisane na stronie podręcznika dotyczącego dynamicznie konfigurowanego masowego hostingu wirtualnego Apache .

Treffynnon
źródło
Pod warunkiem, że możesz użyć wildcard subdomains, zobacz moje rozwiązanie, aby to zrobić w .htaccess.
Dan Bray
Nie sądzę, aby wirtualny host mógł zostać dodany z .htaccess, ale także denerwuje mnie bezpieczeństwo. Od 2.4 powinno być możliwe wybranie katalogu podstawowego zależnego od nazwy hosta (ale metoda Dana też ma pewne problemy) Rozważ:RewriteRule "^/?(.*)" "http://%{HTTP_HOST}/%{HTTP_HOST}/$1" [L,R,NE]
symcbean
Zauważ, że kod PHP implementujący to NIE MOŻE działać jako identyfikator UID serwera WWW (powinien być jako dedykowany użytkownik przez sudo)
symcbean
12

Możesz najpierw zezwolić na każdą subdomenę, a następnie sprawdzić, czy jest ona prawidłowa. Na przykład:

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

Wewnątrz index.phpmożesz wyodrębnić subdomenę za pomocą:

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

Ale wszystko to wymaga, aby twój serwer internetowy akceptował każdą nazwę subdomeny.

Gumbo
źródło
3
Ponadto wymaga, aby Twój serwer DNS rozpoznawał każdą nazwę subdomeny.
chaos
1
Widziałem to na innych stronach internetowych, z pewnością nie muszą za każdym razem rozwiązywać każdej subdomeny?
Ben McRae,
1
To zależy od tego, co przez to rozumiesz. Jeśli masz na myśli, za każdym razem, gdy ktoś w Internecie wyszukuje foo.somedomain.com i nie jest buforowany, jego serwer DNS musi go rozwiązać, to tak.
chaos
Jeśli masz na myśli, czy muszą skonfigurować rekordy DNS specjalnie dla każdej domeny, zobacz odpowiedź Treffynnona.
chaos
ok dzięki za to. nie całkiem rozumiem, co Treffynnon ma na myśli, określając symbol wieloznaczny w vhostie?
Ben McRae,
6

Łatwiej było mi to robić z PHP. W rzeczywistości tworzy subdomenę w cPanel i utwórz folder pod żądaną nazwą domeny. Jak zrobisz to ręcznie w cPanel, ale wszystko to jest robione w milisekundach przez prostą funkcję PHP. Nie trzeba klikać :)

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.
źródło
Sprawdź, czy został pomyślnie utworzony w cPanel i sprawdź przez FTP (lub menedżer plików), co znajduje się w folderze public_html / subdomain. Jeśli masz ustawienie cPanel, dodawanie rzeczy podczas tworzenia subdomeny nie jest związane z tworzeniem subdomen w locie.
Adrian P.
No nie zostało utworzone w cPanel
Ruchi
W takim razie nie masz wystarczających uprawnień w cPanel. Czy to współdzielony hosting VPS czy serwer dedykowany?
Adrian P.,
Może być wiele powodów, dla których nie utworzono subdomeny. Nie ma związku z powyższym skryptem, ale z konfiguracją DNS. Przeczytaj to i poproś o pomoc na forach cPanel. forums.cpanel.net/threads/subdomains-not-working.228132
Adrian P.,
5

Najłatwiejszym sposobem jest przekierowanie wszystkich subdomen (z symbolem wieloznacznym *) tak, aby wskazywały na twój / wwwroot. Następnie umieść .htaccess w tym folderze z następującym kodem:

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]

Spowoduje to, że każdy podfolder folderu / wwwroot będzie akceptowany przez subdomenę (nazwa_folderu.domena.com).

Znalezione lata temu na http://www.webmasterworld.com/apache/3163397.htm

Glavić
źródło
4

To nie ma nic wspólnego z .htaccess. Musisz skonfigurować rekordy DNS i hosting wirtualny dla subdomen.

chaos
źródło
4

Mod_vhost_alias jest odpowiednim modułem do tego.

Za pomocą jednej linii możesz powiedzieć Apache, aby szukał we właściwym miejscu, z haszowaniem katalogów itp. Na przykład linia:

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

powie Apache, aby ustawił katalog główny dokumentu na / http / users / s / u / subdomain, gdy zostanie poproszony o subdomain.yourdomain.com

Julien Tartarin
źródło
0

Myślę, że DNS z dziką kartą z Dynamic Mass Virtual Hosting Apache jest również rozsądnym rozwiązaniem. Chociaż nigdy tego nie próbowałem.

Jeśli potrzebujesz skalować w poziomie do wielu serwerów lub inne rozwiązania po prostu nie działają, polecam użycie serwera DNS opartego na bazie danych. W przeszłości z powodzeniem korzystałem z MyDNS . Ponieważ używa MySQL (lub PostgreSQL), możesz aktualizować swój DNS w locie za pomocą PHP lub cokolwiek innego. Kod nie wygląda tak, jakby był aktualizowany od jakiegoś czasu, ale jest to DNS, a zatem nie do końca nowatorski.

Barrett Conrad
źródło
0

Metody tworzenia poddomeny z symbolami wieloznacznymi

Najpierw musisz utworzyć ustawienia DNS za pomocą edytora DNS serwera.

  1. Utwórz Arekord w ustawieniach DNS z symbolem *wieloznacznym w adresie IP serwera.

    * 1400 IN A ip_address

  2. Utwórz ponownie Arekord w ustawieniach DNS z adresem hosta @lub domain_name.tldadresem IP serwera. tld oznacza domeny najwyższego poziomu lub rozszerzenia domen, takie jak .com, .org itp.

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

  3. Utwórz CNAMErekord, taki jak:

    www 1400 IN A domainname.tld

  4. Utwórz subdomenę z *symbolem wieloznacznym*.domain.tld
  5. Utwórz htaccess w swoim katalogu subdomeny *.domain.tldi umieść ten kod:

    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

    Przetestuj swoją pierwszą subdomenę z symbolem wieloznacznym, na przykład example.domainname.tld

Jeśli nie jesteś zainteresowany przekazywaniem danych jako parametru za pomocą htaccess, możesz również uzyskać dane za pomocą następującego kodowania:

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

i używaj swojej zmiennej globalnej w dowolnym miejscu, np global $get_data.

echo $get_data->data; //example

(uwaga: ta klasa jest używana głównie do uzyskiwania dokładnej nazwy subdomeny z http_host., ponieważ niektóre dodatkowe nazwy połączone przed twoją subdomeną mają również zastosowanie, np www.example.domainname.tld. Ten zwrot $_GET['data']='wwww'Więc proponuję użyć $_SERVER['http_host']do uzyskania dokładnych wartości zamiast używania$_SERVER['query_string'] lub przekazanych parametrów htaccess w Twoja strona indeksu)

6. Przyspieszenie wykonywania tych subdomen z symbolami wieloznacznymi, użyj N sekund w TTL - USTAWIENIA DNS.

7.Sprawdź subdomenę po podanym czasie ttl (600 - 10 minut), np. => http://abc.domain.tld

(uwaga: subdomeny z symbolem wieloznacznym nie zastępują istniejących subdomen. Ponieważ priorytet zawsze ma znaczenie dla istniejących subdomen)

karthikeyan ganesan
źródło