Sdílet prostřednictvím


Připojení ke službě Azure SQL Database a jejich dotazování pomocí balíčku Node.js a mssql npm

Platí pro:Azure SQL Database

Tento rychlý start popisuje, jak připojit aplikaci k databázi ve službě Azure SQL Database a provádět dotazy pomocí Node.js a mssql. Tento rychlý start se řídí doporučeným přístupem bez hesla pro připojení k databázi.

Připojení bez hesel pro vývojáře

Připojení bez hesla nabízejí bezpečnější mechanismus pro přístup k prostředkům Azure. Následující základní kroky slouží k připojení ke službě Azure SQL Database pomocí připojení bez hesla v tomto článku:

  • Připravte prostředí na ověřování bez hesla.
    • Pro místní prostředí: Používá se vaše osobní identita. Tuto identitu je možné načíst z integrovaného vývojového prostředí, rozhraní příkazového řádku nebo jiných místních vývojových nástrojů.
    • V cloudovém prostředí se používá spravovaná identita .
  • Ověřte se v prostředí pomocí DefaultAzureCredential knihovny identit Azure a získejte ověřené přihlašovací údaje.
  • Pomocí ověřených přihlašovacích údajů vytvořte objekty klienta Azure SDK pro přístup k prostředkům.

Další informace o připojeních bez hesel najdete v centru bez hesel.

Požadavky

Konfigurace databázového serveru

Zabezpečená bez hesla připojení ke službě Azure SQL Database vyžadují určité konfigurace databáze. Ověřte na logickém serveru v Azure následující nastavení, abyste se mohli správně připojit ke službě Azure SQL Database v místním i hostovaným prostředí:

  1. V případě místních vývojových připojení se ujistěte, že je váš logický server nakonfigurovaný tak, aby umožňoval připojení IP adresy místního počítače a dalších služeb Azure:

    • Přejděte na stránku Sítě vašeho serveru.

    • Přepněte přepínač Vybrané sítě, aby se zobrazily další možnosti konfigurace.

    • Vyberte Přidat adresu IPv4 klienta (xx.xx.xx.xx) a přidejte pravidlo brány firewall, které povolí připojení z adresy IPv4 místního počítače. Případně můžete také vybrat + Přidat pravidlo brány firewall a podle svého výběru zadat konkrétní IP adresu.

    • Ujistěte se, že je zaškrtnuté políčko Povolit službám a prostředkům Azure přístup k tomuto serveru .

      Snímek obrazovky znázorňující, jak nakonfigurovat pravidla brány firewall

      Varování

      Povolení přístupu ke službám a prostředkům Azure pro přístup k tomuto nastavení serveru není doporučeným postupem zabezpečení pro produkční scénáře. Skutečné aplikace by měly implementovat bezpečnější přístupy, jako jsou silnější omezení brány firewall nebo konfigurace virtuální sítě.

      Další informace o konfiguracích zabezpečení databáze najdete v následujících zdrojích informací:

  2. Server musí mít také povolené ověřování Microsoft Entra a musí mít přiřazený účet správce Microsoft Entra. Pro místní vývojová připojení by měl být účet správce Microsoft Entra účtem, ke kterým se můžete také přihlásit do sady Visual Studio nebo Azure CLI místně. Můžete ověřit, zda má váš server povolené ověřování Microsoft Entra na stránce Microsoft Entra ID vašeho logického serveru.

    Snímek obrazovky znázorňující povolení ověřování Microsoft Entra

  3. Pokud používáte osobní účet Azure, ujistěte se, že máte nastaveny a nakonfigurovány Microsoft Entra ID pro Azure SQL Database, abyste mohli přiřadit svůj účet jako správce serveru. Pokud používáte podnikový účet, bude pravděpodobně již nakonfigurován pro vás Microsoft Entra ID.

Vytvoření projektu

Kroky v této části vytvoří Node.js rozhraní REST API.

  1. Vytvořte pro projekt nový adresář a přejděte do něj.

  2. Inicializace projektu spuštěním následujícího příkazu v terminálu:

    npm init -y
    
  3. Nainstalujte požadované balíčky použité v ukázkovém kódu v tomto článku:

    npm install mssql express swagger-ui-express yamljs dotenv
    
  4. Otevřete projekt v editoru Visual Studio Code.

    code .
    
  5. Otevřete soubor package.json a po vlastnosti s názvem přidejte následující vlastnost a hodnotu pro konfiguraci projektu pro moduly ESM.

    "type": "module",
    

Vytvoření kódu aplikace Express.js

Pokud chcete vytvořit aplikaci Express.js OpenAPI, vytvoříte několik souborů:

Soubor Popis
.env.development Místní soubor prostředí jen pro vývoj
index.js Hlavní soubor aplikace, který spouští aplikaci Express.js na portu 3000.
person.js Express.js /person směruje soubor rozhraní API pro zpracování operací CRUD.
openapi.js Trasování Express.js /api-docs pro uživatelské rozhraní OpenAPI Explorer. Kořen přesměruje na tuto trasu.
openApiSchema.yml Soubor schématu OpenAPI 3.0 definující rozhraní API pro osoby
config.js Konfigurační soubor pro čtení proměnných prostředí a vytvoření příslušného objektu připojení mssql.
database.js Třída pro práci s databázemi za účelem provádění CRUD operací v Azure SQL pomocí npm balíčku mssql.
./vscode/settings.json Během nasazování ignorujte soubory podle vzoru globu.
  1. Vytvořte soubor index.js a přidejte následující kód:

    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. Vytvořte person.js směrovací soubor a přidejte následující kód:

    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;
    

    Pro ověřování bez hesla změňte parametr předaný z createDatabaseConnectionSQLAuthentication na PasswordlessConfig.

    const database = await createDatabaseConnection(PasswordlessConfig);
    
  3. Vytvořte soubor trasy openapi.js a přidejte následující kód pro Průzkumníka uživatelského rozhraní 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. Vytvořte soubor openApiSchema.yml a přidejte následující kód, aby Průzkumník uživatelského rozhraní OpenAPI věděl, jaká rozhraní API a modely se mají zobrazit:

    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
    

Konfigurace objektu připojení mssql

Balíček mssql implementuje připojení ke službě Azure SQL Database poskytnutím konfiguračního nastavení pro typ ověřování.

  1. V editoru Visual Studio Code vytvořte soubor config.js a přidejte následující konfigurační kód mssql pro ověření ve službě 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
      }
    };
    

Vytvořte soubor pro lokální proměnné prostředí

Vytvoření souboru .env.development pro místní proměnné prostředí

Přidejte následující text a aktualizujte hodnoty pro <YOURSERVERNAME> a <YOURDATABASENAME>.

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

Poznámka:

Objekty konfigurace bez hesla jsou bezpečné pro potvrzení do správy zdrojového kódu, protože neobsahují žádné tajné kódy, jako jsou uživatelská jména, hesla nebo přístupové klíče.

Přidání kódu pro připojení ke službě Azure SQL Database

  1. Vytvořte soubor database.js a přidejte následující kód:

    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;
    };
    

Místní testování aplikace

Aplikace je připravená k místnímu otestování. Ujistěte se, že jste přihlášení ke cloudu Azure v editoru Visual Studio Code pomocí stejného účtu, který jste nastavili jako správce vaší databáze.

  1. Spusťte aplikaci pomocí následujícího příkazu. Aplikace se spustí na portu 3000.

    NODE_ENV=development node index.js
    

    Tabulka Person se vytvoří v databázi při spuštění této aplikace.

  2. V prohlížeči přejděte do Průzkumníka OpenAPI na adrese http://localhost:3000.

  3. Na stránce s uživatelským rozhraním Swagger rozbalte metodu POST a vyberte Vyzkoušet.

  4. Upravte ukázkový JSON tak, aby zahrnoval hodnoty pro vlastnosti. Vlastnost ID je ignorována.

    Snímek obrazovky znázorňující, jak otestovat rozhraní API

  5. Vyberte Spustit a přidejte do databáze nový záznam. Rozhraní API vrátí úspěšnou odpověď.

  6. Rozbalte metodu GET na stránce uživatelského rozhraní Swagger a vyberte Vyzkoušet. Vyberte Spustit a vrátí se osoba, kterou jste právě vytvořili.

Konfigurace projektu pro nasazení archivu ZIP

  1. Vytvořte složku .vscode a ve složce vytvořte soubor settings.json.

  2. Přidáním následujícího příkazu můžete ignorovat proměnné prostředí a závislosti během nasazování souboru ZIP.

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

Nasazení do Azure App Service

Aplikace je připravená k nasazení do Azure. Visual Studio Code může vytvořit službu Aplikace Azure a nasadit aplikaci v jednom pracovním postupu.

  1. Ujistěte se, že je aplikace zastavená.

  2. Pokud jste to ještě neudělali, přihlaste se k Azure tak, že v paletě příkazů vyberete příkaz Azure: Přihlásit se ke cloudu (Ctrl + + P).

  3. V okně Azure Explorer editoru Visual Studio Code klikněte pravým tlačítkem na uzel App Services a vyberte Create New Web App (Advanced).

  4. K vytvoření služby App Service použijte následující tabulku:

    Podnět Hodnota
    Zadejte globálně jedinečný název nové webové aplikace. Zadejte výzvu, například azure-sql-passwordless. Přidejte na konec jedinečný řetězec, například 123.
    Vyberte skupinu prostředků pro nové zdroje. Vyberte +Vytvořit novou skupinu prostředků a pak vyberte výchozí název.
    Vyberte běhové prostředí. Vyberte verzi LTS balíčku Node.js.
    Vyberte operační systém. Vyberte Linux.
    Vyberte umístění pro nové prostředky. Vyberte umístění blízko vás.
    Vyberte plán služby App Service pro Linux. Vyberte Vytvořit nový plán služby App Service. Pak vyberte výchozí název.
    Vyberte cenovou úroveň. Vyberte free (F1).
    Vyberte prostředek Application Insights pro vaši aplikaci. Vyberte Přeskočit prozatím.
  5. Počkejte na oznámení o vytvoření vaší aplikace, než budete pokračovat.

  6. V Azure Exploreru rozbalte uzel Služby App Services a klikněte pravým tlačítkem na novou aplikaci.

  7. Vyberte Nasadit do webové aplikace.

    Snímek obrazovky editoru Visual Studio Code v Průzkumníku Azure se zvýrazněnou možností Nasadit do webové aplikace

  8. Vyberte kořenovou složku projektu JavaScriptu.

  9. Jakmile se zobrazí automaticky otevírané okno editoru Visual Studio Code, vyberte Nasadit.

Po dokončení nasazení aplikace v Azure nefunguje správně. Stále potřebujete nakonfigurovat zabezpečené připojení mezi službou App Service a databází SQL pro načtení dat.

Připojení služby App Service ke službě Azure SQL Database

Pro připojení instance služby App Service ke službě Azure SQL Database jsou potřeba následující kroky:

  1. Vytvořte spravovanou identitu pro službu App Service.
  2. Vytvořte uživatele databáze SQL a přidružte ho ke spravované identitě služby App Service.
  3. Přiřaďte databázovému uživateli role SQL, které umožňují čtení, zápis a potenciálně další oprávnění.

K dispozici je několik nástrojů pro implementaci těchto kroků:

Service Connector je nástroj, který zjednodušuje ověřená připojení mezi různými službami v Azure. Konektor služby v současné době podporuje připojení služby App Service k databázi Azure SQL přes Azure CLI pomocí az webapp connection create sql příkazu. Tento jediný příkaz dokončí tři kroky uvedené výše.

Vytvořte spravovanou identitu pomocí konektoru služby

V Cloud Shellu na webu Azure Portal spusťte následující příkaz. Cloud Shell má nejnovější verzi Azure CLI. Nahraďte proměnné <> vlastními hodnotami.

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

Ověření nastavení aplikace služby App Service

Změny provedené konektorem služby můžete ověřit v nastavení služby App Service.

  1. V editoru Visual Studio Code v Průzkumníku Azure klikněte pravým tlačítkem na váš App Service a vyberte Otevřít v portálu.

  2. Přejděte na stránku Identita vaší služby App Service. Pod kartou Systém přiřazený by měl být stav nastaven na Zapnuto. Tato hodnota znamená, že pro vaši aplikaci byla povolena spravovaná identita přiřazená systémem.

  3. Přejděte na stránku Konfigurace vaší služby App Service. Na kartě Nastavení aplikace byste měli vidět několik proměnných prostředí, které už byly v objektu konfigurace mssql.

    • AZURE_SQL_SERVER
    • AZURE_SQL_DATABASE
    • AZURE_SQL_PORT
    • AZURE_SQL_AUTHENTICATIONTYPE

    Neodstraňovat ani měnit názvy nebo hodnoty vlastností.

Otestování nasazené aplikace

Přejděte na adresu URL aplikace a otestujte, že funguje připojení ke službě Azure SQL Database. Adresu URL aplikace najdete na stránce přehledu služby App Service.

Osoba, kterou jste vytvořili místně, by se měla zobrazit v prohlížeči. Gratulujeme! Vaše aplikace je teď připojená ke službě Azure SQL Database v místním i hostovaným prostředí.

Doporučení

Pokud při testování dojde k vnitřní chybě serveru 500, může to být způsobeno konfigurací sítě databáze. Ověřte, že je váš logický server nakonfigurovaný s nastavením popsanými v části Konfigurace databáze .

Ukliďte zdroje

Po dokončení práce se službou Azure SQL Database odstraňte prostředek, abyste se vyhnuli nezamýšleným nákladům.

  1. Na panelu hledání na webu Azure Portal vyhledejte Azure SQL a vyberte odpovídající výsledek.

  2. Vyhledejte a vyberte databázi v seznamu databází.

  3. Na stránce Přehled služby Azure SQL Database vyberte Odstranit.

  4. Na stránce Azure, kterou opravdu chcete odstranit, která se otevře, zadejte název databáze, abyste ji potvrdili, a pak vyberte Odstranit.

Ukázkový kód

Ukázkový kód pro tuto aplikaci je k dispozici:

Další kroky