我们正在构建一个 Nestjs 应用程序,该应用程序使用 Typeorm 连接到 Azure Postgresql 灵活数据库服务器。我们遵循使用托管身份和 Entra 令牌的无密码方法。我们的应用程序能够连接到数据库,但在令牌过期后(在我们的例子中为 24 小时),我们的应用程序会因数据库连接未自动刷新而关闭。
还有其他人遇到过这个问题吗?
我们尝试在 23 小时后使用 https://learn.microsoft.com/en-us/javascript/api/overview/azure/identity-readme?view=azure-node-latest 刷新令牌,但我们可以看到即使在 24 小时后也没有生成新的令牌。
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ManagedIdentityCredential } from '@azure/identity';
@Module({
imports: [
TypeOrmModule.forRootAsync({
useFactory: async () => {
const credential = new ManagedIdentityCredential(); // Use ManagedIdentityCredential
// Fetch the access token
const tokenResponse = await credential.getToken('https://ossrdbms-aad.database.windows.net/.default');
return {
type: 'postgres',
host: '<YOUR_DATABASE_SERVER_NAME>.postgres.database.azure.com', // Replace with your server name
port: 5432,
username: '<YOUR_AAD_USER>@<YOUR_DATABASE_SERVER_NAME>', // Replace with your Azure AD user
password: tokenResponse.token, // Use the fetched access token as the password
database: '<YOUR_DATABASE_NAME>', // Replace with your database name
ssl: { rejectUnauthorized: false }, // Adjust based on your SSL requirements
entities: [/* Your entities here */],
synchronize: true, // Set to false in production
};
},
}),
],
})
export class DatabaseModule {}
import { Module } from '@nestjs/common';
import { DatabaseModule } from './database/database.module'; // Adjust the path as necessary
@Module({
imports: [
DatabaseModule, // Import the DatabaseModule here
// Other modules can be added here as needed
],
controllers: [],
providers: [],
})
export class AppModule {}
我会使用 cron 作业将
dataSource
注入到服务中,以定期刷新令牌。但是,有一些警告:如果在重新启动连接时收到请求,它们可能会失败。
以下是如何刷新令牌并使用托管身份的新访问令牌重新初始化
DataSource
的示例:
@Injectable()
export class TokenRefresher {
constructor(
private readonly dataSource: DataSource
) {}
@Cron('*/15 * * * * *')
async refresh(): Promise<Credentials[]> {
// here custom logic to restart the database
const destroyDatabase = true;
if (destroyDatabase) {
const credential = new ManagedIdentityCredential(); // Use ManagedIdentityCredential
// Fetch the access token
const tokenResponse = await credential.getToken(
"https://ossrdbms-aad.database.windows.net/.default"
);
await this.dataSource.destroy();
this.dataSource.setOptions({
password: tokenResponse.password,
});
await this.dataSource.initialize();
}
}
}