yunzerwebsiteallinone/docs/域名系统配置指南.md
2026-06-03 10:09:03 +08:00

12 KiB
Raw Blame History

多租户二级域名绑定官网系统 - 配置指南

一、后端配置ThinkPHP

1. 中间件配置

文件:tp/app/common/middleware/DomainParse.php

需要修改的配置项第14-15行

$adminDomains = ['admin.xxx.com'];      // 后台域名
$platformDomains = ['www.xxx.com'];       // 平台官网域名

根据实际情况修改为你购买的域名。

2. 已创建的API接口

接口 路径 方法 说明
主域名列表 /admin/domain/pool GET 获取域名池列表
启用的主域名 /admin/domain/pool/getEnabledDomains GET 获取可用主域名
创建主域名 /admin/domain/pool/create POST 添加主域名
更新主域名 /admin/domain/pool/update POST 编辑主域名
删除主域名 /admin/domain/pool/delete/:id DELETE 删除主域名
切换主域名状态 /admin/domain/pool/toggleStatus POST 启用/禁用
租户域名列表 /admin/domain/tenant GET 获取所有租户域名
我的域名 /admin/domain/tenant/myDomains GET 租户获取自己的域名
申请域名 /admin/domain/tenant/apply POST 租户申请二级域名
审核域名 /admin/domain/tenant/audit POST 管理员审核
切换租户域名状态 /admin/domain/tenant/toggleStatus POST 禁用域名

二、前端配置Vue

1. 页面路由

需要在后台管理系统中添加菜单:

菜单名称 路径 组件
主域名池 /cms/domain/pool apps/cms/domain/pool.vue
域名审核 /cms/domain/audit apps/cms/domain/audit.vue
我的域名 /tenant/domain basicSettings/tenants/domain.vue

2. 菜单SQL可选

-- 主域名池管理菜单
INSERT INTO `mete_menu` (`name`, `title`, `path`, `component`, `parent_id`, `sort`, `status`) 
VALUES ('DomainPool', '主域名池', '/cms/domain/pool', 'apps/cms/domain/pool', 0, 0, 1);

-- 租户域名审核菜单
INSERT INTO `mete_menu` (`name`, `title`, `path`, `component`, `parent_id`, `sort`, `status`) 
VALUES ('DomainAudit', '域名审核', '/cms/domain/audit', 'apps/cms/domain/audit', 0, 0, 1);

三、Nginx 配置

完整配置示例

注意啊要先把ssl申请下来再用上面的配置不然报错

注意啊要先把ssl申请下来再用上面的配置不然报错

注意啊要先把ssl申请下来再用上面的配置不然报错

yunzer.com.cn

server
{
    listen 80;
    listen 443 ssl;
    listen 443 quic;
    http2 on;
    server_name yunzer.com.cn ~^(?<subdomain>.+)\.yunzer\.com\.cn$;
    index index.php index.html index.htm default.php default.htm default.html;
    root /www/wwwroot/api.yunzer.cn/public;
    
    #CERT-APPLY-CHECK--START
    include /www/server/panel/vhost/nginx/well-known/yunzer.com.cn.conf;
    #CERT-APPLY-CHECK--END
    include /www/server/panel/vhost/nginx/extension/yunzer.com.cn/*.conf;
    
    #SSL-START SSL相关配置请勿删除或修改下一行带注释的404规则
    #error_page 404/404.html;
    #HTTP_TO_HTTPS_START
    set $isRedcert 1;
    if ($server_port != 443) {
        set $isRedcert 2;
    }
    if ( $uri ~ /\.well-known/ ) {
        set $isRedcert 1;
    }
    if ($isRedcert != 1) {
        rewrite ^(/.*)$ https://$host$1 permanent;
    }
    #HTTP_TO_HTTPS_END
    ssl_certificate    /www/server/panel/vhost/cert/yunzer.com.cn/fullchain.pem;
    ssl_certificate_key    /www/server/panel/vhost/cert/yunzer.com.cn/privkey.pem;
    ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_tickets on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    add_header Strict-Transport-Security "max-age=31536000";
    add_header Alt-Svc 'quic=":443"; h3=":443"; h3-29=":443"; h3-27=":443";h3-25=":443"; h3-T050=":443"; h3-Q050=":443";h3-Q049=":443";h3-Q048=":443"; h3-Q046=":443"; h3-Q043=":443"';
    error_page 497  https://$host$request_uri;
    #SSL-END

    #ERROR-PAGE-START  错误页配置,可以注释、删除或修改
    error_page 404 /404.html;
    #error_page 502 /502.html;
    #ERROR-PAGE-END

    #PHP-INFO-START  PHP引用配置可以注释或修改
    include enable-php-82.conf;
    #PHP-INFO-END

    #REWRITE-START URL重写规则引用,修改后将导致面板设置的伪静态规则失效
    include /www/server/panel/vhost/rewrite/yunzer.com.cn.conf;
    #REWRITE-END

    # 禁止访问的敏感文件
    location ~* (\.user.ini|\.htaccess|\.htpasswd|\.env.*|\.project|\.bashrc|\.bash_profile|\.bash_logout|\.DS_Store|\.gitignore|\.gitattributes|LICENSE|README\.md|CLAUDE\.md|CHANGELOG\.md|CHANGELOG|CONTRIBUTING\.md|TODO\.md|FAQ\.md|composer\.json|composer\.lock|package(-lock)?\.json|yarn\.lock|pnpm-lock\.yaml|\.\w+~|\.swp|\.swo|\.bak(up)?|\.old|\.tmp|\.temp|\.log|\.sql(\.gz)?|docker-compose\.yml|docker\.env|Dockerfile|\.csproj|\.sln|Cargo\.toml|Cargo\.lock|go\.mod|go\.sum|phpunit\.xml|phpunit\.xml|pom\.xml|build\.gradl|pyproject\.toml|requirements\.txt|application(-\w+)?\.(ya?ml|properties))$
    {
        return 404;
    }
    
    # 禁止访问的敏感目录
    location ~* /(\.git|\.svn|\.bzr|\.vscode|\.claude|\.idea|\.ssh|\.github|\.npm|\.yarn|\.pnpm|\.cache|\.husky|\.turbo|\.next|\.nuxt|node_modules|runtime)/ {
        return 404;
    }

    #一键申请SSL证书验证目录相关设置
    location ~ \.well-known{
        allow all;
    }

    #禁止在证书验证目录放入敏感文件
    if ( $uri ~ "^/\.well-known/.*\.(php|jsp|py|js|css|lua|ts|go|zip|tar\.gz|rar|7z|sql|bak)$" ) {
        return 403;
    }

    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
    {
        expires      30d;
        error_log /dev/null;
        access_log /dev/null;
    }

    location ~ .*\.(js|css)?$
    {
        expires      12h;
        error_log /dev/null;
        access_log /dev/null;
    }

    # 传递子域名参数给TP
    location ~ [^/]\.php(/|$) {
        include enable-php-82.conf;
        fastcgi_param HTTP_SUBDOMAIN $subdomain;
        fastcgi_param HTTP_MAIN_DOMAIN yunzer.com.cn;
    }

    # TP路由重写正确格式无$s变量
    if (!-e $request_filename) {
        rewrite ^(.*)$ /index.php?$1 last;
    }

    access_log  /www/wwwlogs/yunzer.com.cn.log;
    error_log  /www/wwwlogs/yunzer.com.cn.error.log;
}
dh2.fun

server
{
    listen 80;
    listen 443 ssl;
    listen 443 quic;
    http2 on;
    server_name dh2.fun ~^(?<subdomain>.+)\.dh2\.fun$;
    index index.php index.html index.htm default.php default.htm default.html;
    root /www/wwwroot/api.yunzer.cn/public;
    
    #CERT-APPLY-CHECK--START
    include /www/server/panel/vhost/nginx/well-known/dh2.fun.conf;
    #CERT-APPLY-CHECK--END
    include /www/server/panel/vhost/nginx/extension/dh2.fun/*.conf;
    
    #SSL-START SSL相关配置请勿删除或修改下一行带注释的404规则
    #error_page 404/404.html;
    #HTTP_TO_HTTPS_START
    set $isRedcert 1;
    if ($server_port != 443) {
        set $isRedcert 2;
    }
    if ( $uri ~ /\.well-known/ ) {
        set $isRedcert 1;
    }
    if ($isRedcert != 1) {
        rewrite ^(/.*)$ https://$host$1 permanent;
    }
    #HTTP_TO_HTTPS_END
    ssl_certificate    /www/server/panel/vhost/cert/dh2.fun/fullchain.pem;
    ssl_certificate_key    /www/server/panel/vhost/cert/dh2.fun/privkey.pem;
    ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_tickets on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    add_header Strict-Transport-Security "max-age=31536000";
    add_header Alt-Svc 'quic=":443"; h3=":443"; h3-29=":443"; h3-27=":443";h3-25=":443"; h3-T050=":443"; h3-Q050=":443";h3-Q049=":443";h3-Q048=":443"; h3-Q046=":443"; h3-Q043=":443"';
    error_page 497  https://$host$request_uri;
    #SSL-END

    #ERROR-PAGE-START  错误页配置,可以注释、删除或修改
    error_page 404 /404.html;
    #error_page 502 /502.html;
    #ERROR-PAGE-END

    #PHP-INFO-START  PHP引用配置可以注释或修改
    include enable-php-82.conf;
    #PHP-INFO-END

    #REWRITE-START URL重写规则引用,修改后将导致面板设置的伪静态规则失效
    include /www/server/panel/vhost/rewrite/dh2.fun.conf;
    #REWRITE-END

    # 禁止访问的敏感文件
    location ~* (\.user.ini|\.htaccess|\.htpasswd|\.env.*|\.project|\.bashrc|\.bash_profile|\.bash_logout|\.DS_Store|\.gitignore|\.gitattributes|LICENSE|README\.md|CLAUDE\.md|CHANGELOG\.md|CHANGELOG|CONTRIBUTING\.md|TODO\.md|FAQ\.md|composer\.json|composer\.lock|package(-lock)?\.json|yarn\.lock|pnpm-lock\.yaml|\.\w+~|\.swp|\.swo|\.bak(up)?|\.old|\.tmp|\.temp|\.log|\.sql(\.gz)?|docker-compose\.yml|docker\.env|Dockerfile|\.csproj|\.sln|Cargo\.toml|Cargo\.lock|go\.mod|go\.sum|phpunit\.xml|phpunit\.xml|pom\.xml|build\.gradl|pyproject\.toml|requirements\.txt|application(-\w+)?\.(ya?ml|properties))$
    {
        return 404;
    }
    
    # 禁止访问的敏感目录
    location ~* /(\.git|\.svn|\.bzr|\.vscode|\.claude|\.idea|\.ssh|\.github|\.npm|\.yarn|\.pnpm|\.cache|\.husky|\.turbo|\.next|\.nuxt|node_modules|runtime)/ {
        return 404;
    }

    #一键申请SSL证书验证目录相关设置
    location ~ \.well-known{
        allow all;
    }

    #禁止在证书验证目录放入敏感文件
    if ( $uri ~ "^/\.well-known/.*\.(php|jsp|py|js|css|lua|ts|go|zip|tar\.gz|rar|7z|sql|bak)$" ) {
        return 403;
    }

    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
    {
        expires      30d;
        error_log /dev/null;
        access_log /dev/null;
    }

    location ~ .*\.(js|css)?$
    {
        expires      12h;
        error_log /dev/null;
        access_log /dev/null;
    }

    # 传递子域名参数给TP
    location ~ [^/]\.php(/|$) {
        include enable-php-82.conf;
        fastcgi_param HTTP_SUBDOMAIN $subdomain;
        fastcgi_param HTTP_MAIN_DOMAIN dh2.fun;
    }

    # TP路由重写正确格式无$s变量
    if (!-e $request_filename) {
        rewrite ^(.*)$ /index.php?$1 last;
    }

    access_log  /www/wwwlogs/dh2.fun.log;
    error_log  /www/wwwlogs/dh2.fun.error.log;
}

注意啊要先把ssl申请下来再用上面的配置不然报错

注意啊要先把ssl申请下来再用上面的配置不然报错

注意啊要先把ssl申请下来再用上面的配置不然报错


四、DNS 解析配置

在你的域名服务商(阿里云、腾讯云等)控制台添加:

记录类型 主机记录 记录值
A @ 服务器IP
A www 服务器IP
A admin 服务器IP
CNAME * @

其中 * 表示泛解析,会匹配所有二级域名。


五、使用流程

1. 管理员操作

  1. 登录后台管理系统
  2. 进入「主域名池」管理,添加已购买的主域名(如 xxx.com
  3. 审核租户申请的二级域名

2. 租户操作

  1. 租户登录后台
  2. 进入「我的域名」页面
  3. 选择主域名,填写二级前缀,提交申请
  4. 等待管理员审核
  5. 审核通过后,访问 http://二级域名.xxx.com 即可访问官网

3. 访问规则

  • admin.xxx.com → 后台管理系统
  • www.xxx.com / xxx.com → 平台官网
  • 其他二级域名 → 对应租户的官网

六、注意事项

  1. 泛域名解析确保DNS已配置泛解析 *.yourdomain.com
  2. 域名状态:只有状态为"已生效"的域名才能正常访问
  3. 软删除:所有删除操作都是软删除,数据不会真正删除
  4. tenant_id:所有数据通过 tenant_id 做租户隔离

七、文件清单

后端

  • tp/app/admin/controller/Cms/Domain/DomainPoolController.php
  • tp/app/admin/controller/Cms/Domain/TenantDomainController.php
  • tp/app/admin/route/routes/domain.php
  • tp/app/common/middleware/DomainParse.php

前端

  • backend/src/api/domain.js
  • backend/src/views/apps/cms/domain/pool.vue
  • backend/src/views/apps/cms/domain/audit.vue
  • backend/src/views/basicSettings/tenants/domain.vue