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

使用Knex结合系统分配身份连接SQL Server时遇登录失败错误

Knex使用Azure系统分配身份连接SQL Server时出现空用户登录失败错误

我尝试用Knex结合Azure系统分配身份连接Microsoft SQL Server,已按要求配置认证方式,但始终收到如下错误:

ConnectionError: Login failed for user ''
at ConnectionError (/node_modules/tedious/lib/errors.js:13:12)
at Parser.<anonymous> (/node_modules/tedious/lib/connection.js:1194:51)
at Parser.emit (node:events:517:28)
at Readable.<anonymous> (/node_modules/tedious/lib/token/token-stream-parser.js:27:14)
at Readable.emit (node:events:517:28)
at addChunk (node/streams/readable:368:12)
at readableAddChunk (node/streams/readable:341:9)
at Readable.push (node/streams/readable:278:10)
at next (node/streams/from:98:31)
at process.processTicksAndRejections (node/process/task_queues:95:5)

环境与配置情况

  • 使用Knex连接Microsoft SQL Server
  • 已配置Knex采用Azure系统分配身份认证
  • 运行环境(App Service/VM等)已启用并配置系统分配身份
  • 确认配置参数无误,但仍出现空用户登录失败问题

我的连接配置代码:

dbConfig = {
  client: config.ENV.TNT_DB_CLIENT,
  connection: {
    server: config.ENV.TNT_DB_SERVER,
    authentication: {
      type: 'azure-active-directory-msi-app-service',
      options: {
        tenantId: config.ENV.AZURE_TENANT_ID
      }
    },
    options: {
       database: config.ENV.TNT_DATABASE,
       trustServerCertificate: false,
       encrypt: true,
       requestTimeout: 300000
     }
  },
  plugins: [knexPlugin()],
  pool: {
      acquireTimeoutMillis: 300000,
      min: parseInt(config.ENV.TNT_DB_MIN_CONNECTION),
      max: parseInt(config.ENV.TNT_DB_MAX_CONNECTION)
  },
  migrations: {
    tableName: 'knex_migrations'
  },
  requestTimeout: 300000,
  connectionTimeout: 300000,
  acquireConnectionTimeout: 300000
};

可能的解决方向

1. 验证Knex与Tedious版本兼容性

Knex依赖tedious作为SQL Server驱动,部分旧版本tedious对Azure MSI身份认证的支持存在bug,无法正确获取MSI令牌,进而导致空用户登录失败。建议:

  • 将tedious升级到最新稳定版(如>=16.0.0)
  • 同步升级Knex到对应兼容版本

2. 检查MSI身份的数据库权限配置

确保系统分配的MSI身份已被正确授予SQL Server访问权限:

  • 登录Azure Portal,进入目标SQL Server的「Azure Active Directory」选项卡
  • 添加系统分配身份为SQL Server外部用户,并授予对应数据库角色(如db_datareader/db_datawriter)
  • 执行SQL查询验证用户是否存在于目标数据库:SELECT name FROM sys.database_principals WHERE name = N'<MSI身份名称>'

3. 匹配运行环境调整认证类型

如果运行环境不是App Service(如虚拟机、容器),需将认证类型改为azure-active-directory-msi-vm:

authentication: {
  type: 'azure-active-directory-msi-vm', // 非App Service环境使用该类型
  options: {
    tenantId: config.ENV.AZURE_TENANT_ID
  }
}

4. 清理重复的Timeout配置

当前配置中同时在connection.options和顶层重复设置了timeout参数,可能导致tedious内部逻辑冲突。建议将timeout参数统一放在connection.options中,移除顶层重复配置:

dbConfig = {
  client: config.ENV.TNT_DB_CLIENT,
  connection: {
    server: config.ENV.TNT_DB_SERVER,
    authentication: {
      type: 'azure-active-directory-msi-app-service',
      options: {
        tenantId: config.ENV.AZURE_TENANT_ID
      }
    },
    options: {
       database: config.ENV.TNT_DATABASE,
       trustServerCertificate: false,
       encrypt: true,
       requestTimeout: 300000,
       connectionTimeout: 300000
     }
  },
  plugins: [knexPlugin()],
  pool: {
      acquireTimeoutMillis: 300000,
      min: parseInt(config.ENV.TNT_DB_MIN_CONNECTION),
      max: parseInt(config.ENV.TNT_DB_MAX_CONNECTION)
  },
  migrations: {
    tableName: 'knex_migrations'
  }
};

5. 手动验证MSI令牌获取

添加调试代码确认是否能正常获取MSI令牌,排查环境层面问题:

const { ManagedIdentityCredential } = require('@azure/identity');

async function getToken() {
  const credential = new ManagedIdentityCredential();
  const token = await credential.getToken('https://database.windows.net/.default');
  console.log('MSI Token:', token);
}
getToken().catch(console.error);

若无法获取令牌,需检查运行环境的MSI配置(如MSI_ENDPOINT、MSI_SECRET环境变量是否存在),或重新启用系统分配身份。

内容的提问来源于stack exchange,提问作者Sumit Patel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 07:00:19