Partager via


Se connecter à Azure SQL Database et l’interroger en utilisant Node.js et le package npm mssql

S’applique à : Azure SQL Database

Ce guide de démarrage rapide explique comment connecter une application à une base de données dans Azure SQL Database et effectuer des requêtes avec Node.js et mssql. Ce guide de démarrage rapide suit l’approche sans mot de passe recommandée pour se connecter à la base de données.

Connexions sans mot de passe pour les développeurs

Les connexions sans mot de passe offrent un mécanisme plus sécurisé pour accéder aux ressources Azure. Les étapes générales suivantes sont utilisées pour se connecter à une base de données Azure SQL à l’aide de connexions sans mot de passe dans cet article :

  • Préparez votre environnement pour l’authentification sans mot de passe.
    • Pour un environnement local : votre identité personnelle est utilisée. Cette identité peut être extraite d’un IDE, d’une CLI ou d’autres outils de développement locaux.
    • Pour un environnement cloud : une identité managée est utilisée.
  • Authentifiez-vous dans l’environnement à l’aide des DefaultAzureCredential de la bibliothèque Azure Identity pour obtenir des identifiants vérifiés.
  • Utilisez les identifiants vérifiés pour créer des objets client du kit de développement logiciel (SDK) Azure pour l’accès aux ressources.

Vous pouvez en apprendre plus sur les connexions sans mot de passe sur le Hub des connexions sans mot de passe.

Prérequis

Configurer le serveur de base de données

Les connexions sécurisées et sans mot de passe à Azure SQL Database nécessitent certaines configurations de base de données. Vérifiez les paramètres suivants sur votre serveur logique dans Azure pour vous connecter correctement à Azure SQL Database dans les environnements locaux et hébergés :

  1. Pour les connexions de développement local, vérifiez que votre serveur logique est configuré pour autoriser l’adresse IP de votre ordinateur local et d’autres services Azure à se connecter :

    • Accédez à la page Réseau de votre serveur.

    • Activez la case d’option Réseaux sélectionnés pour voir des options de configuration supplémentaires.

    • Sélectionnez Ajouter l’adresse IPv4 de votre client (xx.xx.xx.xx.xx.xx) pour ajouter une règle de pare-feu qui activera les connexions à partir de l’adresse IPv4 de votre ordinateur local. Vous pouvez également sélectionner + Ajouter une règle de pare-feu pour entrer une adresse IP spécifique de votre choix.

    • Vérifiez que la case Autoriser les services et les ressources Azure à accéder à ce serveur est cochée.

      Capture d’écran montrant comment configurer des règles de pare-feu.

      Avertissement

      L’activation du paramètre Autoriser les services et les ressources Azure à accéder à ce serveur n’est pas une pratique de sécurité recommandée pour les scénarios de production. Les applications réelles doivent implémenter des approches plus sécurisées, telles que des restrictions de pare-feu ou des configurations de réseau virtuel plus strictes.

      Vous pouvez en apprendre davantage sur les configurations de sécurité de base de données avec les ressources suivantes :

  2. Le serveur doit également activer l’authentification Microsoft Entra et disposer d’un compte d’administrateur Microsoft Entra affecté. Pour les connexions de développement local, le compte d’administrateur de Microsoft Entra doit être un compte que vous pouvez également connecter localement à Visual Studio ou à Azure CLI. Vous pouvez vérifier si l’authentification Microsoft Entra est activée sur la page Microsoft Entra ID de votre serveur logique.

    Capture d’écran montrant l’activation de l’authentification Microsoft Entra.

  3. Si vous utilisez un compte Azure personnel, assurez-vous d’avoir Microsoft Entra installé et configuré dans la base de données Azure SQL afin d’assigner votre compte en tant qu’administrateur de serveur. En revanche, si vous utilisez un compte d’entreprise, il est fort probable que Microsoft Entra ID soit déjà configuré pour vous.

Créer le projet

Les étapes de cette section créent une API REST Node.js.

  1. Créez un répertoire pour le projet et accédez-y.

  2. Initialisez le projet en exécutant la commande suivante dans le terminal :

    npm init -y
    
  3. Installez les packages requis utilisés dans l’exemple de code de cet article :

    npm install mssql express swagger-ui-express yamljs dotenv
    
  4. Ouvrez le projet dans Visual Studio Code.

    code .
    
  5. Ouvrez le fichier package.json et ajoutez la propriété et la valeur suivantes après la propriété name pour configurer le projet pour les modules ESM.

    "type": "module",
    

Créer le code d’application Express.js

Pour créer l’application OpenAPI Express.js, vous allez créer plusieurs fichiers :

Fichier Description
.env.development Fichier d’environnement de développement local uniquement.
index.js Fichier d’application principal, qui démarre l’application Express.js sur le port 3000.
person.js Fichier de l’API de routage Express.js /person pour gérer les opérations CRUD.
openapi.js Route Express.js /api-docs pour l’interface utilisateur de l’explorateur OpenAPI. Root redirige vers cette route.
openApiSchema.yml Fichier de schéma OpenAPI 3.0 qui définit l’API Person.
config.js Fichier de configuration pour lire les variables d’environnement et construire l’objet de connexion mssql approprié.
database.js Classe de base de données pour gérer les opérations CRUD Azure SQL à l’aide du package npm mssql.
./vscode/settings.json Ignorer les fichiers du modèle Glob durant le déploiement.
  1. Créez un fichier index.js et ajoutez-y le code suivant :

    import express from 'express';
    
    // Import App routes
    import person from './person.js';
    import openapi from './openapi.js';
    
    const port = process.env.PORT || 3000;
    
    const app = express();
    
    // Connect App routes
    app.use('/api-docs', openapi);
    app.use('/persons', person);
    app.use('*', (_, res) => {
      res.redirect('/api-docs');
    });
    
    // Start the server
    app.listen(port, () => {
      console.log(`Server started on port ${port}`);
    });
    
  2. Créez un fichier de routage person.jset ajoutez-y le code suivant :

    import express from 'express';
    import { 
      passwordConfig as SQLAuthentication, 
      noPasswordConfig as PasswordlessConfig 
    } from './config.js';
    import { createDatabaseConnection } from './database.js';
    
    const router = express.Router();
    router.use(express.json());
    
    const database = await createDatabaseConnection(SQLAuthentication);
    
    router.get('/', async (req, res) => {
      try {
        // Return a list of persons
    
        const persons = await database.readAll();
        console.log(`persons: ${JSON.stringify(persons)}`);
        res.status(200).json(persons);
      } catch (err) {
        res.status(500).json({ error: err?.message });
      }
    });
    
    router.post('/', async (req, res) => {
      try {
        // add a person
        const person = req.body;
        console.log(`person: ${JSON.stringify(person)}`);
        const rowsAffected = await database.create(person);
        res.status(201).json({ rowsAffected });
      } catch (err) {
        res.status(500).json({ error: err?.message });
      }
    });
    
    router.get('/:id', async (req, res) => {
      try {
        // Get the person with the specified ID
        const personId = req.params.id;
        console.log(`personId: ${personId}`);
        if (personId) {
          const result = await database.read(personId);
          console.log(`persons: ${JSON.stringify(result)}`);
          res.status(200).json(result);
        } else {
          res.status(404);
        }
      } catch (err) {
        res.status(500).json({ error: err?.message });
      }
    });
    
    router.put('/:id', async (req, res) => {
      try {
        // Update the person with the specified ID
        const personId = req.params.id;
        console.log(`personId: ${personId}`);
        const person = req.body;
    
        if (personId && person) {
          delete person.id;
          console.log(`person: ${JSON.stringify(person)}`);
          const rowsAffected = await database.update(personId, person);
          res.status(200).json({ rowsAffected });
        } else {
          res.status(404);
        }
      } catch (err) {
        res.status(500).json({ error: err?.message });
      }
    });
    
    router.delete('/:id', async (req, res) => {
      try {
        // Delete the person with the specified ID
        const personId = req.params.id;
        console.log(`personId: ${personId}`);
    
        if (!personId) {
          res.status(404);
        } else {
          const rowsAffected = await database.delete(personId);
          res.status(204).json({ rowsAffected });
        }
      } catch (err) {
        res.status(500).json({ error: err?.message });
      }
    });
    
    export default router;
    

    Pour l’authentification sans mot de passe, modifiez le paramètre passé à createDatabaseConnection de SQLAuthentication à PasswordlessConfig.

    const database = await createDatabaseConnection(PasswordlessConfig);
    
  3. Créez un fichier de routage openapi.js et ajoutez-y le code suivant pour l’explorateur de l’interface utilisateur OpenAPI :

    import express from 'express';
    import { join, dirname } from 'path';
    import swaggerUi from 'swagger-ui-express';
    import yaml from 'yamljs';
    import { fileURLToPath } from 'url';
    
    const __dirname = dirname(fileURLToPath(import.meta.url));
    
    const router = express.Router();
    router.use(express.json());
    
    const pathToSpec = join(__dirname, './openApiSchema.yml');
    const openApiSpec = yaml.load(pathToSpec);
    
    router.use('/', swaggerUi.serve, swaggerUi.setup(openApiSpec));
    
    export default router;
    

Configurer l’objet de connexion mssql

Le package mssql implémente la connexion à Azure SQL Database en fournissant un paramètre de configuration pour un type d’authentification.

  1. Dans Visual Studio Code, créez un fichier config.js et ajoutez-y le code de configuration mssql suivant pour l’authentification auprès d’Azure SQL Database.

    import * as dotenv from 'dotenv';
    
    if(process.env.NODE_ENV === 'development') {
      dotenv.config({ path: `.env.${process.env.NODE_ENV}`, debug: true });
    }
    
    // TIP: Port must be a number, not a string!
    const server = process.env.AZURE_SQL_SERVER;
    const database = process.env.AZURE_SQL_DATABASE;
    const port = +process.env.AZURE_SQL_PORT;
    const type = process.env.AZURE_SQL_AUTHENTICATIONTYPE;
    const user = process.env.AZURE_SQL_USER;
    const password = process.env.AZURE_SQL_PASSWORD;
    
    export const noPasswordConfig = {
      server,
      port,
      database,
      authentication: {
        type
      },
      options: {
        encrypt: true
      }
    };
    
    export const passwordConfig = {
      server,
      port,
      database,
      user,
      password,
      options: {
        encrypt: true
      }
    };
    

Créer un fichier de variables d'environnement

Créer un fichier .env.development pour vos variables d’environnement locales

Ajoutez le texte suivant et mettez à jour avec vos valeurs pour <YOURSERVERNAME> et <YOURDATABASENAME>.

AZURE_SQL_SERVER=<YOURSERVERNAME>.database.windows.net
AZURE_SQL_DATABASE=<YOURDATABASENAME>
AZURE_SQL_PORT=1433
AZURE_SQL_AUTHENTICATIONTYPE=azure-active-directory-default

Remarque

Les objets de configuration sans mot de passe peuvent être commités en toute sécurité dans le contrôle de code source, car ils ne contiennent pas de secrets, comme des noms d’utilisateur, des mots de passe ou des clés d’accès.

Ajouter le code pour se connecter à Azure SQL Database

  1. Créez un fichier database.js et ajoutez-y le code suivant :

    import sql from 'mssql';
    
    let database = null;
    
    export default class Database {
      config = {};
      poolconnection = null;
      connected = false;
    
      constructor(config) {
        this.config = config;
      }
    
      async connect() {
        try {
          this.poolconnection = await sql.connect(this.config);
          this.connected = true;
          console.log('Database connected successfully.');
          return this.poolconnection;
        } catch (error) {
          console.error('Error connecting to the database:', error);
          this.connected = false;
        }
      }
    
      async disconnect() {
        try {
          if (this.connected) {
            await this.poolconnection.close();
            this.connected = false;
            console.log('Database disconnected successfully.');
          }
        } catch (error) {
          console.error('Error disconnecting from the database:', error);
        }
      }
    
      async executeQuery(query) {
        const request = this.poolconnection.request();
        const result = await request.query(query);
    
        return result.rowsAffected[0];
      }
    
      async create(data) {
        const request = this.poolconnection.request();
    
        request.input('firstName', sql.NVarChar(255), data.firstName);
        request.input('lastName', sql.NVarChar(255), data.lastName);
    
        const result = await request.query(
          `INSERT INTO Person (firstName, lastName) VALUES (@firstName, @lastName)`
        );
    
        return result.rowsAffected[0];
      }
    
      async readAll() {
        const request = this.poolconnection.request();
        const result = await request.query(`SELECT * FROM Person`);
    
        return result.recordsets[0];
      }
    
      async read(id) {
        const request = this.poolconnection.request();
        const result = await request
          .input('id', sql.Int, +id)
          .query(`SELECT * FROM Person WHERE id = @id`);
    
        return result.recordset[0];
      }
    
      async update(id, data) {
        const request = this.poolconnection.request();
    
        request.input('id', sql.Int, +id);
        request.input('firstName', sql.NVarChar(255), data.firstName);
        request.input('lastName', sql.NVarChar(255), data.lastName);
    
        const result = await request.query(
          `UPDATE Person SET firstName=@firstName, lastName=@lastName WHERE id = @id`
        );
    
        return result.rowsAffected[0];
      }
    
      async delete(id) {
        const idAsNumber = Number(id);
    
        const request = this.poolconnection.request();
        const result = await request
          .input('id', sql.Int, idAsNumber)
          .query(`DELETE FROM Person WHERE id = @id`);
    
        return result.rowsAffected[0];
      }
    
      async createTable() {
        if (process.env.NODE_ENV === 'development') {
          this.executeQuery(
            `IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Person')
             BEGIN
               CREATE TABLE Person (
                 id int NOT NULL IDENTITY, 
                 firstName varchar(255), 
                 lastName varchar(255)
               );
             END`
          )
            .then(() => {
              console.log('Table created');
            })
            .catch((err) => {
              // Table may already exist
              console.error(`Error creating table: ${err}`);
            });
        }
      }
    }
    
    export const createDatabaseConnection = async (passwordConfig) => {
      database = new Database(passwordConfig);
      await database.connect();
      await database.createTable();
      return database;
    };
    

Tester l’application en local

L’application est prête à être testée localement. Vérifiez que vous êtes connecté au cloud Azure dans Visual Studio Code avec le même compte que l’administrateur de votre base de données.

  1. Exécutez l’application avec la commande suivante. Cette application démarre sur le port 3000.

    NODE_ENV=development node index.js
    

    La table Person est créée dans la base de données lorsque vous exécutez cette application.

  2. Dans un navigateur, accédez à l’explorateur OpenAPI à l’adresse http://localhost:3000.

  3. Dans la page de l’interface utilisateur Swagger, développez la méthode POST, puis sélectionnez Essayer.

  4. Modifiez l’exemple JSON pour inclure les valeurs des propriétés. La propriété ID est ignorée.

    Capture d’écran montrant comment tester l’API.

  5. Sélectionnez Exécuter pour ajouter un nouvel enregistrement à la base de données. L’API retourne une réponse de succès.

  6. Développez la méthode GET sur la page de l’interface utilisateur Swagger, puis sélectionnez Essayer. Sélectionnez Exécuter, et la personne que vous venez de créer est retournée.

Configurer un projet pour le déploiement zip.

  1. Créez un dossier .vscode et créez un fichier settings.json dans le dossier.

  2. Ajoutez le code suivant pour ignorer les variables d’environnement et les dépendances pendant le déploiement zip.

    {
        "appService.zipIgnorePattern": ["./.env*","node_modules{,/**}"]
    }
    

Déployer dans Azure App Service

L’application est prête à être déployée sur Azure. Visual Studio Code peut créer une instance Azure App Service et déployer votre application au cours d’un même workflow.

  1. Vérifiez que l’application est arrêtée.

  2. Connectez-vous à Azure, si ce n’est pas déjà fait, en sélectionnant la commande Azure : Se connecter au cloud Azure dans la palette de commandes (Ctrl + Maj + P)

  3. Dans la fenêtre Azure Explorer de Visual Studio Code, cliquez avec le bouton droit sur le nœud App Services et sélectionnez Créer une application web (avancé).

  4. Utilisez le tableau suivant pour créer App Service :

    Prompt Valeur
    Entrez un nom global unique pour la nouvelle application web. Entrez une invite similaire à azure-sql-passwordless. Ajoutez après une chaîne unique telle que 123.
    Sélectionnez un groupe de ressources pour les nouvelles ressources. Sélectionnez +Créer un groupe de ressources, puis sélectionnez le nom par défaut.
    Sélectionnez une pile de runtime. Sélectionnez une version LTS de la pile Node.js.
    Sélectionnez un système d’exploitation. Sélectionnez Linux.
    Sélectionnez un emplacement pour les nouvelles ressources. Sélectionnez un emplacement proche de vous.
    Sélectionnez un plan App Service Linux. Sélectionnez Créer un plan App Service,, puis sélectionnez le nom par défaut.
    Sélectionnez un niveau tarifaire. Sélectionnez Gratuit (F1).
    Sélectionnez une ressource Application Insights pour votre application. Sélectionnez Ignorer pour le moment.
  5. Avant de continuer, attendez l’affichage de la notification indiquant que votre application a été créée.

  6. Dans Azure Explorer, développez le nœud App Services et cliquez avec le bouton droit sur votre nouvelle application.

  7. Sélectionnez Déployer sur l’application web.

    Capture d’écran de Visual Studio Code montrant Azure Explorer avec l’icône Déployer sur l’application web mise en évidence.

  8. Sélectionnez le dossier racine du projet JavaScript.

  9. Lorsque la fenêtre contextuelle Visual Studio Code s’affiche, sélectionnez Déployer.

À la fin du déploiement, l’application ne fonctionne pas correctement sur Azure. Vous devez toujours configurer la connexion sécurisée entre App Service et la base de données SQL pour récupérer vos données.

Connecter App Service à Azure SQL Database

Les étapes suivantes sont requises pour connecter l’instance App Service à Azure SQL Database :

  1. Créez une identité managée pour App Service.
  2. Créez un utilisateur de base de données SQL et associez-le à l’identité managée App Service.
  3. Attribuez des rôles SQL à l’utilisateur de base de données qui octroient des autorisations de lecture, d’écriture et éventuellement d’autres autorisations.

Plusieurs outils sont disponibles pour implémenter ces étapes :

Service Connector est un outil qui simplifie les connexions authentifiées entre différents services dans Azure. Service Connector prend actuellement en charge la connexion d’App Service à une base de données Azure SQL en utilisant la commande az webapp connection create sql dans Azure CLI. Cette commande unique effectue les trois étapes mentionnées ci-dessus pour vous.

Créer l’identité managée avec Service Connector

Exécutez la commande suivante dans le Cloud Shell du portail Azure. Le Cloud Shell utilise la dernière version d’Azure CLI. Remplacez les variables dans <> par vos propres valeurs.

az webapp connection create sql \
    -g <app-service-resource-group> \
    -n <app-service-name> \
    --tg <database-server-resource-group> \
    --server <database-server-name> \
    --database <database-name> \
    --system-identity

Vérifier les paramètres de l’application App Service

Vous pouvez vérifier les modifications apportées par Service Connector sur les paramètres App Service.

  1. Dans Visual Studio Code, dans Azure Explorer, cliquez avec le bouton droit sur votre application App Service et sélectionnez Ouvrir dans le portail.

  2. Accédez à la page Identité de votre App Service. Sous l’onglet Affecté par le système , l’État doit être défini sur Activé. Cette valeur signifie qu’une identité managée affectée par le système a été activée pour votre application.

  3. Accédez à la page Configuration de votre App Service. Sous l’onglet Paramètres de l’application, vous devez voir plusieurs variables d’environnement, lesquelles se trouvaient déjà dans l’objet de configuration mssql.

    • AZURE_SQL_SERVER
    • AZURE_SQL_DATABASE
    • AZURE_SQL_PORT
    • AZURE_SQL_AUTHENTICATIONTYPE

    Ne supprimez pas et ne modifiez pas les noms de propriétés ou leurs valeurs.

Tester l’application déployée

Accédez à l’URL de l’application pour tester que la connexion à Azure SQL Database fonctionne. Vous pouvez localiser l’URL de votre application dans la page de vue d’ensemble d’App Service.

La personne que vous avez créée localement devrait s’afficher dans le navigateur. Félicitations ! Votre application est maintenant connectée à Azure SQL Database dans les environnements locaux et hébergés.

Conseil

Si vous obtenez une erreur Serveur interne 500 pendant le test, ce sont peut-être vos configurations réseau de base de données qui sont en cause. Vérifiez que votre serveur logique est configuré avec les paramètres décrits dans la section Configurer la base de données.

Nettoyer les ressources

Une fois que vous avez terminé d’utiliser Azure SQL Database, supprimez la ressource pour éviter les coûts imprévus.

  1. Dans la barre de recherche du portail Azure, recherchez Azure SQL et sélectionnez le résultat correspondant.

  2. Recherchez et sélectionnez votre base de données dans la liste.

  3. Dans la page Vue d’ensemble d’Azure SQL Database, sélectionnez Supprimer.

  4. Dans la page Voulez-vous vraiment supprimer... qui s’ouvre, tapez le nom de la base de données pour confirmer, puis sélectionnez Supprimer.

Exemple de code

L’exemple de code pour cette application est disponible :

Étapes suivantes