You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用vhost动态创建子域名 实现用户注册后自动生成username.domain.com

Express 动态子域名实现方案

核心实现思路:放弃预先为每个用户单独注册vhost规则的方式,改用泛域名匹配+请求时动态校验用户名合法性的方案,无需在用户注册时做额外的路由配置,只要用户数据入库即可正常访问对应子域名。


具体修改步骤

1. 调整vhost匹配规则为泛匹配

把原代码中硬编码的单用户vhost规则替换为适配所有用户名的泛匹配规则,所有符合*.你的域名格式的请求都会被转发到subdomain实例处理。
将原代码中的:

app.use(vhost(`username.${domain}`, subdomain));

替换为:

app.use(vhost(`*.${domain}`, subdomain));

2. 新增子域名用户名校验中间件

在subdomain的所有路由和中间件最前面,新增用户名校验逻辑:从请求头提取子域名对应的用户名,查询数据库校验用户是否存在,存在则挂载用户信息到请求对象供后续路由使用,不存在直接返回错误。
示例代码:

// 替换为你实际的User模型路径
const User = require('./api/models/user');

// 该中间件必须放在subdomain所有其他中间件、路由之前
subdomain.use(async (req, res, next) => {
  // 拆分host获取子域名部分,例如请求为zhangsan.localhost:3000时,拆分结果为['zhangsan', 'localhost', '3000']
  const hostParts = req.headers.host.split('.');
  // 提取用户名,若你的主域名为多级(如domain.com.cn),需要调整截取逻辑
  const username = hostParts[0];

  try {
    // 校验用户是否存在
    const existUser = await User.findOne({ username: username });
    if (!existUser) {
      return res.status(404).json({ error: '对应用户子域名不存在' });
    }
    // 挂载用户信息到请求对象,后续路由可直接调用req.subdomainUser获取当前子域名对应用户
    req.subdomainUser = existUser;
    next();
  } catch (err) {
    return res.status(500).json({ error: '子域名校验失败' });
  }
});

3. 用户注册逻辑无需额外调整

用户注册成功后只要用户名正常写入数据库,对应的username.domain.com即可直接访问,不需要做额外配置操作。


注意事项

  • 本地测试:需修改系统hosts文件,将测试用的子域名(如zhangsan.localhost)指向127.0.0.1,或配置本地DNS泛解析规则。
  • 生产环境:需在域名服务商处配置泛域名解析*.domain.com指向你的服务器IP;若使用Nginx等反向代理,需配置透传Host请求头,确保express可以拿到正确的原始域名。

不推荐方案说明:若采用用户注册时动态调用app.use()新增vhost规则的方案,服务重启后所有动态注册的规则会丢失,需要启动时全量遍历用户表重新注册,用户量大时启动耗时长,性能表现差。

内容的提问来源于stack exchange,提问作者Tony George

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 22:24:03