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

349 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 多租户二级域名绑定官网系统 - 配置指南
## 一、后端配置ThinkPHP
### 1. 中间件配置
文件:`tp/app/common/middleware/DomainParse.php`
需要修改的配置项第14-15行
```php
$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可选
```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`