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 swagger-ui-express yamljs
    
  4. Installez le package de développement utilisé dans l’exemple de code de cet article :

    npm install --save-dev dotenv 
    
  5. Ouvrez le projet dans Visual Studio Code.

    code .
    
  6. 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 { config } from './config.js';
    import Database from './database.js';
    
    // Import App routes
    import person from './person.js';
    import openapi from './openapi.js';
    
    const port = process.env.PORT || 3000;
    
    const app = express();
    
    // Development only - don't do in production
    // Run this to create the table in the database
    if (process.env.NODE_ENV === 'development') {
      const database = new Database(config);
      database
        .executeQuery(
          `CREATE TABLE Person (id int NOT NULL IDENTITY, firstName varchar(255), lastName varchar(255));`
        )
        .then(() => {
          console.log('Table created');
        })
        .catch((err) => {
          // Table may already exist
          console.error(`Error creating table: ${err}`);
        });
    }
    
    // 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 { config } from './config.js';
    import Database from './database.js';
    
    const router = express.Router();
    router.use(express.json());
    
    // Development only - don't do in production
    console.log(config);
    
    // Create database object
    const database = new Database(config);
    
    router.get('/', async (_, 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 {
        // Create 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;
    
    
  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;
    
  4. Créez un fichier de schéma openApiSchema.yml et ajoutez-y le contenu YAML suivant :

    openapi: 3.0.0
    info:
      version: 1.0.0
      title: Persons API
    paths:
      /persons:
        get:
          summary: Get all persons
          responses:
            '200':
              description: OK
              content:
                application/json:
                  schema:
                    type: array
                    items:
                      $ref: '#/components/schemas/Person'
        post:
          summary: Create a new person
          requestBody:
            required: true
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/Person'
          responses:
            '201':
              description: Created
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Person'
      /persons/{id}:
        parameters:
          - name: id
            in: path
            required: true
            schema:
              type: integer
        get:
          summary: Get a person by ID
          responses:
            '200':
              description: OK
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Person'
            '404':
              description: Person not found
        put:
          summary: Update a person by ID
          requestBody:
            required: true
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/Person'
          responses:
            '200':
              description: OK
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Person'
            '404':
              description: Person not found
        delete:
          summary: Delete a person by ID
          responses:
            '204':
              description: No Content
            '404':
              description: Person not found
    components:
      schemas:
        Person:
          type: object
          properties:
            id:
              type: integer
              readOnly: true
            firstName:
              type: string
            lastName:
              type: string
    

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';
    dotenv.config({ path: `.env.${process.env.NODE_ENV}`, debug: true });
    
    const server = process.env.AZURE_SQL_SERVER;
    const database = process.env.AZURE_SQL_DATABASE;
    const port = parseInt(process.env.AZURE_SQL_PORT);
    const type = process.env.AZURE_SQL_AUTHENTICATIONTYPE;
    
    export const config = {
        server,
        port,
        database,
        authentication: {
            type
        },
        options: {
            encrypt: true
        }
    };
    
  2. Créez un fichier .env.development pour vos variables d’environnement locales, ajoutez-y le texte suivant, et remplacez <YOURSERVERNAME> et <YOURDATABASENAME> par vos propres valeurs.

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

Notes

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.

  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{,/**}"]
    }
    

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';
    
    export default class Database {
      config = {};
      poolconnection = null;
      connected = false;
    
      constructor(config) {
        this.config = config;
        console.log(`Database: config: ${JSON.stringify(config)}`);
      }
    
      async connect() {
        try {
          console.log(`Database connecting...${this.connected}`);
          if (this.connected === false) {
            this.poolconnection = await sql.connect(this.config);
            this.connected = true;
            console.log('Database connection successful');
          } else {
            console.log('Database already connected');
          }
        } catch (error) {
          console.error(`Error connecting to database: ${JSON.stringify(error)}`);
        }
      }
    
      async disconnect() {
        try {
          this.poolconnection.close();
          console.log('Database connection closed');
        } catch (error) {
          console.error(`Error closing database connection: ${error}`);
        }
      }
    
      async executeQuery(query) {
        await this.connect();
        const request = this.poolconnection.request();
        const result = await request.query(query);
    
        return result.rowsAffected[0];
      }
    
      async create(data) {
        await this.connect();
        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() {
        await this.connect();
        const request = this.poolconnection.request();
        const result = await request.query(`SELECT * FROM Person`);
    
        return result.recordsets[0];
      }
    
      async read(id) {
        await this.connect();
    
        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) {
        await this.connect();
    
        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) {
        await this.connect();
    
        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];
      }
    }
    

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.

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 sur GitHub.

Étapes suivantes