Herstellen einer Verbindung mit Azure SQL-Datenbank und Abfragen mithilfe von Node.js und des npm-Pakets „mssql“
Gilt für: Azure SQL-Datenbank
In dieser Schnellstartanleitung wird beschrieben, wie Sie eine Verbindung einer Anwendung mit einer Datenbank in Azure SQL-Datenbank herstellen und Abfragen mithilfe von Node.js und mssql ausführen. In dieser Schnellstartanleitung wird der empfohlene kennwortlose Ansatz zum Herstellen einer Verbindung mit der Datenbank verwendet.
Kennwortlose Verbindungen für Entwickler
Kennwortlose Verbindungen stellen einen sichereren Mechanismus für den Zugriff auf Azure-Ressourcen dar. Nach den folgenden allgemeinen Schritten wird in diesem Artikel eine Verbindung mit Azure SQL-Datenbank mittels kennwortloser Verbindungen hergestellt:
- Bereiten Sie Ihre Umgebung auf die kennwortfreie Authentifizierung vor.
- Für eine lokale Umgebung: Es wird Ihre persönliche Identität verwendet. Diese Identität kann von einer IDE, CLI oder anderen lokalen Entwicklungstools abgerufen werden.
- Für eine Cloudumgebung: Es wird eine verwaltete Identität verwendet.
- Authentifizieren Sie sich in der Umgebung unter Verwendung der
DefaultAzureCredential
aus der Azure Identity-Bibliothek zum Abrufen verifizierter Anmeldedaten. - Verwenden Sie die verifizierten Anmeldedaten, um Azure SDK-Clientobjekte für den Ressourcenzugriff zu erstellen.
Sie können mehr über kennwortlose Verbindungen auf dem kennwortlosen Hub erfahren.
Voraussetzungen
- Ein Azure-Abonnement
- Eine Datenbank in Azure SQL-Datenbank, die für die Authentifizierung mit Microsoft Entra ID (früher Azure Active Directory) konfiguriert ist. Sie können zum Erstellen einer Datenbank den Schnellstart zum Erstellen einer Datenbank verwenden.
- Bash-fähige Shell
- Node.js LTS
- Visual Studio Code
- App Service-Erweiterung für Visual Studio Code
- Aktuelle Version der Azure CLI
Konfigurieren des Datenbankservers
Sichere, kennwortlose Verbindungen mit Azure SQL-Datenbank erfordern bestimmte Datenbankkonfigurationen. Überprüfen Sie die folgenden Einstellungen auf Ihrem logischen Server in Azure, um eine ordnungsgemäße Verbindung mit Azure SQL-Datenbank in lokalen und gehosteten Umgebungen herzustellen:
Stellen Sie für Verbindungen bei der lokalen Entwicklung sicher, dass Ihr logischer Server so konfiguriert ist, dass die IP-Adresse Ihres lokalen Computers und andere Azure-Dienste eine Verbindung herstellen können:
Wechseln Sie zur Seite Netzwerk für Ihren Server.
Verwenden Sie das Optionsfeld Ausgewählte Netzwerke, um zusätzliche Konfigurationsoptionen anzuzeigen.
Wählen Sie Client-IPv4-Adresse (xx.xx.xx.xx) hinzufügen aus, um eine Firewallregel hinzuzufügen, die Verbindungen von der IPv4-Adresse Ihres lokalen Computers ermöglicht. Alternativ können Sie auch + Firewallregel hinzufügen auswählen, um eine bestimmte IP-Adresse Ihrer Wahl einzugeben.
Vergewissern Sie sich, dass das Kontrollkästchen Azure-Diensten und -Ressourcen den Zugriff auf diesen Server gestatten aktiviert ist.
Warnung
Das Aktivieren der Einstellung Azure-Diensten und -Ressourcen den Zugriff auf diesen Server gestatten ist kein empfohlenes Sicherheitsverfahren für Produktionsszenarien. Echte Anwendungen sollten sicherere Ansätze implementieren, z. B. stärkere Firewalleinschränkungen oder Konfigurationen mit virtuellen Netzwerken.
Weitere Informationen zum Konfigurieren der Datenbanksicherheit finden Sie in den folgenden Ressourcen:
Der Server muss auch die Microsoft Entra-Authentifizierung aktiviert haben und ein Microsoft Entra-Administratorkonto zugewiesen haben. Bei lokalen Entwicklungsverbindungen sollte das Microsoft Entra-Administratorkonto ein Konto sein, mit dem Sie sich auch lokal bei Visual Studio oder der Azure CLI anmelden können. Sie können überprüfen, ob der Server die Microsoft Entra-Authentifizierung auf der Microsoft Entra-ID-Seite Ihres logischen Servers aktiviert hat.
Wenn Sie ein persönliches Azure-Konto verwenden, stellen Sie sicher, dass Sie Microsoft Entra für Azure SQL Database eingerichtet und konfiguriert haben, um Ihr Konto als Server-Admin zuzuweisen. Wenn Sie ein Unternehmenskonto verwenden, ist die Microsoft Entra ID höchstwahrscheinlich bereits für Sie konfiguriert.
Erstellen des Projekts
Mit den Schritten in diesem Abschnitt wird eine Node.js-REST-API erstellt.
Erstellen Sie ein neues Verzeichnis für das Projekt, und rufen Sie es auf.
Initialisieren Sie das Projekt, indem Sie den folgenden Befehl im Terminal ausführen:
npm init -y
Installieren Sie die erforderlichen Pakete, die im Beispielcode in diesem Artikel verwendet werden:
npm install mssql express swagger-ui-express yamljs dotenv
Öffnen Sie das Projekt in Visual Studio Code.
code .
Öffnen Sie die Datei package.json, und fügen Sie die folgende Eigenschaft und den folgenden Wert nach der name-Eigenschaft hinzu, um das Projekt für ESM-Module zu konfigurieren.
"type": "module",
Erstellen von Express.js-Anwendungscode
Zum Erstellen der Express.js-OpenAPI-Anwendung erstellen Sie mehrere Dateien:
Datei | BESCHREIBUNG |
---|---|
.env.development | Lokale Umgebungsdatei nur für die Entwicklung |
index.js | Hauptanwendungsdatei, die die Express.js-App an Port 3000 startet. |
person.js | API-Datei für die Express.js-Route /person zur Verarbeitung von CRUD-Vorgängen |
openapi.js | Express.js-Route /api-docs für die OpenAPI-Explorer-Benutzeroberfläche Vom Stamm wird zu dieser Route umgeleitet. |
openApiSchema.yml | OpenAPI 3.0-Schemadatei, die die Personen-API definiert. |
config.js | Konfigurationsdatei zum Lesen von Umgebungsvariablen und zum Erstellen des entsprechenden mssql-Verbindungsobjekts |
database.js | Datenbankklasse zum Verarbeiten von Azure SQL-CRUD-Vorgängen mithilfe des npm-Pakets mssql |
./vscode/settings.json | Ignorieren von Dateien nach Globmuster während der Bereitstellung |
Erstellen Sie eine Datei vom Typ index.js, und fügen Sie den folgenden Code hinzu:
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}`); });
Erstellen Sie eine Routendatei vom Typ person.js, und fügen Sie den folgenden Code hinzu:
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;
Ändern Sie für die kennwortlose Authentifizierung den Parameter, der an
createDatabaseConnection
übergeben wird, vonSQLAuthentication
inPasswordlessConfig
.const database = await createDatabaseConnection(PasswordlessConfig);
Erstellen Sie eine Routendatei vom Typ opanapi.js, und fügen Sie den folgenden Code für den OpenAPI-UI-Explorer hinzu:
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;
Konfigurieren des mssql-Verbindungsobjekts
Das mssql-Paket implementiert die Verbindung mit Azure SQL-Datenbank, indem eine Konfigurationseinstellung für einen Authentifizierungstyp bereitgestellt wird.
Erstellen Sie in Visual Studio Code eine Datei vom Typ config.js, und fügen Sie den folgenden mssql-Konfigurationscode hinzu, um sich bei Azure SQL-Datenbank zu authentifizieren.
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 } };
Erstellen einer Datei für lokale Umgebungsvariablen
Erstellen einer env.development-Datei für lokale Umgebungsvariablen
Fügen Sie den folgenden Text hinzu, und führen Sie eine Aktualisierung mit den Werten für <YOURSERVERNAME>
und <YOURDATABASENAME>
durch.
AZURE_SQL_SERVER=<YOURSERVERNAME>.database.windows.net
AZURE_SQL_DATABASE=<YOURDATABASENAME>
AZURE_SQL_PORT=1433
AZURE_SQL_AUTHENTICATIONTYPE=azure-active-directory-default
Hinweis
Kennwortlose Konfigurationsobjekte können sicher in die Quellcodeverwaltung committet werden, da sie keine Geheimnisse wie Benutzernamen, Kennwörter oder Zugriffsschlüssel enthalten.
Hinzufügen des Codes zum Herstellen einer Verbindung mit Azure SQL-Datenbank
Erstellen Sie eine Datei vom Typ database.js, und fügen Sie den folgenden Code hinzu:
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; };
Lokales Testen der App
Die App kann lokal getestet werden. Stellen Sie sicher, dass Sie bei der Azure-Cloud in Visual Studio Code mit demselben Konto angemeldet sind, das Sie als Administrator*in für Ihre Datenbank festgelegt haben.
Führen Sie die Anwendung mit dem folgenden Befehl aus: Die App wird am Port 3000 gestartet.
NODE_ENV=development node index.js
Die Tabelle Person wird in der Datenbank erstellt, wenn Sie diese Anwendung ausführen.
Navigieren Sie in einem Browser zum OpenAPI-Explorer unter http://localhost:3000.
Erweitern Sie auf der Swagger-UI-Seite die POST-Methode, und wählen Sie Ausprobieren aus.
Ändern Sie den JSON-Beispielcode, um Werte für die Eigenschaften einzuschließen. Die ID-Eigenschaft wird ignoriert.
Wählen Sie Ausführen aus, um der Datenbank einen neuen Datensatz hinzuzufügen. Die API gibt eine Erfolgsmeldung zurück.
Erweitern Sie auf der Swagger-UI-Seite die GET-Methode, und wählen Sie Ausprobieren aus. Wählen Sie Ausführen aus, und die soeben erstellte Person wird zurückgegeben.
Konfigurieren eines Projekts für die ZIP-Bereitstellung
Erstellen Sie den Ordner
.vscode
und darin eine Datei vom Typ settings.json.Fügen Sie Folgendes hinzu, um Umgebungsvariablen und Abhängigkeiten während der ZIP-Bereitstellung zu ignorieren:
{ "appService.zipIgnorePattern": ["./.env*","node_modules{,/**}"] }
Bereitstellung in Azure App Service
Die App kann jetzt in Azure bereitgestellt werden. Visual Studio Code kann eine Azure App Service-Instanz erstellen und Ihre Anwendung in einem einzigen Workflow bereitstellen.
Vergewissern Sie sich, dass die App beendet wurde.
Melden Sie sich bei Azure an, wenn Sie dies noch nicht getan haben. Wählen Sie dazu in der Befehlspalette den Befehl Azure: Bei Azure-Cloud anmelden aus (STRG + UMSCHALT + P).
Klicken Sie im Fenster Azure Explorer von Visual Studio Code mit der rechten Maustaste auf den Knoten App Services, und wählen Sie Neue Web-App erstellen (Erweitert) aus.
Verwenden Sie die folgende Tabelle, um die App Service-Instanz zu erstellen:
Prompt Wert Geben Sie einen global eindeutigen Namen für die neue Web-App ein. Geben Sie eine Eingabeaufforderung ein, z. B. azure-sql-passwordless
. Hängen Sie eine eindeutige Zeichenfolge wie123
an.„Select a resource group for new resources.“ (Wählen Sie eine Ressourcengruppe für neue Ressourcen aus.) Wählen Sie +Neue Ressourcengruppe erstellen und dann den Standardnamen aus. Wählen Sie einen Runtimestapel aus. Wählen Sie eine LTS-Version des Node.js-Stapels aus. Wählen Sie ein Betriebssystem aus. Wählen Sie Linux aus. „Select a location for new resources.“ (Wählen Sie einen Standort für neue Ressourcen aus.) Wählen Sie einen Standort in Ihrer Nähe aus. Wählen Sie einen Linux-App Service-Plan aus. Wählen Sie Neuen App Service Plan erstellen und dann den Standardnamen aus. Wählen Sie einen Tarif. Wählen Sie Free (F1) aus. Wählen Sie eine Application Insights-Ressource für Ihre App aus. Wählen Sie Vorerst überspringen aus. Warten Sie, bis die Benachrichtigung angezeigt wird, dass Ihre App erstellt wurde, bevor Sie fortfahren.
Erweitern Sie in Azure Explorer den Knoten App Services, und klicken Sie mit der rechten Maustaste auf Ihre neue App.
Wählen Sie die Option In Web-App bereitstellen aus.
Wählen Sie den Stammordner des JavaScript-Projekts aus.
Wenn das Visual Studio Code-Popup angezeigt wird, wählen Sie Bereitstellen aus.
Bei Abschluss der Bereitstellung funktioniert die App in Azure nicht ordnungsgemäß. Sie müssen weiterhin die sichere Verbindung zwischen der App Service- und der SQL-Datenbank-Instanz konfigurieren, um Ihre Daten abzurufen.
Verbinden der App Service-Instanz mit Azure SQL-Datenbank
Die folgenden Schritte sind erforderlich, um die App Service- mit der Azure SQL-Datenbank-Instanz zu verbinden:
- Erstellen Sie eine verwaltete Identität für die App Service-Instanz.
- Erstellen Sie einen SQL-Datenbankbenutzer, und ordnen Sie ihn der verwalteten App Service-Identität zu.
- Weisen Sie dem Datenbankbenutzer SQL-Rollen zu, die über Lese-, Schreib- und möglicherweise andere Berechtigungen verfügen.
Es stehen mehrere Tools zur Implementierung dieser Schritte zur Verfügung:
Der Dienstconnector ist ein Tool, das authentifizierte Verbindungen zwischen verschiedenen Diensten in Azure optimiert. Der Dienstconnector unterstützt derzeit das Verbinden einer App Service-Instanz mit einer Azure SQL-Datenbank-Instanz über die Azure CLI mithilfe des az webapp connection create sql
-Befehls. Dieser einzelne Befehl führt die drei oben genannten Schritte für Sie aus.
Erstellen der verwalteten Identität mit dem Dienstconnector
Führen Sie den nachstehenden Befehl in Cloud Shell im Azure-Portal aus. Cloud Shell verfügt über die neueste Version der Azure CLI. Ersetzen Sie die Variablen in <>
durch Ihre eigenen Werte.
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
Überprüfen der App Service-App-Einstellungen
Sie können die vom Dienstconnector vorgenommenen Änderungen in den App Service-Einstellungen überprüfen.
Klicken Sie in Visual Studio Code in Azure Explorer mit der rechten Maustaste auf Ihre App Service-Instanz, und wählen Sie Im Portal öffnen aus.
Navigieren Sie zur Seite Identität für Ihre App Service-Instanz. Auf der Registerkarte Systemseitig zugewiesen sollte der Status auf Ein festgelegt werden. Dieser Wert bedeutet, dass eine systemseitig zugewiesene verwaltete Identität für Ihre App aktiviert wurde.
Navigieren Sie zur Seite Konfiguration für Ihre App Service-Ressource. Auf der Registerkarte Anwendungseinstellungen sollten mehrere Umgebungsvariablen angezeigt werden, die sich bereits im mssql-Konfigurationsobjekt befanden.
AZURE_SQL_SERVER
AZURE_SQL_DATABASE
AZURE_SQL_PORT
AZURE_SQL_AUTHENTICATIONTYPE
Löschen oder ändern Sie die Eigenschaftsnamen oder -werte nicht.
Testen der bereitgestellten Anwendung
Navigieren Sie zur URL der App, um zu testen, ob die Verbindung mit Azure SQL-Datenbank funktioniert. Sie finden die URL Ihrer App auf der App Service-Übersichtsseite.
Die Person, die Sie lokal erstellt haben, sollte im Browser angezeigt werden. Glückwunsch! Ihre Anwendung ist jetzt in lokalen und gehosteten Umgebungen mit Azure SQL-Datenbank verbunden.
Tipp
Wenn beim Testen ein Fehler 500 (internal Serverfehler) angezeigt wird, kann dies auf die Netzwerkkonfiguration Ihrer Datenbank zurückzuführen sein. Vergewissern Sie sich, dass Ihr logischer Server mit den Einstellungen konfiguriert ist, die im Abschnitt Konfigurieren der Datenbank beschrieben sind.
Bereinigen der Ressourcen
Wenn Sie Ihre Arbeit mit der Azure SQL-Datenbank abgeschlossen haben, löschen Sie die Ressource, um unbeabsichtigte Gebühren zu vermeiden.
Geben Sie in der Suchleiste des Azure-Portals Azure SQL ein, und wählen Sie das entsprechende Ergebnis aus.
Suchen Sie Ihre Datenbank in der Liste der Datenbanken, und wählen Sie sie aus.
Wählen Sie auf der Seite Übersicht Ihrer Azure SQL-Datenbank die Option Löschen aus.
Geben Sie auf der daraufhin geöffneten Azure-Seite Möchten Sie ... löschen zur Bestätigung den Namen Ihrer Datenbank ein, und wählen Sie dann Löschen aus.
Beispielcode
Der Beispielcode für diese Anwendung ist verfügbar: