Condividi tramite


Abilitare la generazione di codice a matrice per le app di autenticazione TOTP in un'app Web core Blazor di ASP.NET

Questo articolo illustra come configurare un'app Web di Blazor base ASP.NET con generazione di codice a matrice per le app di autenticazione TOTP.

Per un'introduzione all'autenticazione a due fattori (2FA) con le app di autenticazione che usano un algoritmo TOTP (One-Time Password Algorithm), vedere Abilitare la generazione di codice a matrice per le app di autenticazione TOTP in ASP.NET Core.

Eseguire lo scaffolding del componente Enable Authenticator nell'app

Seguire le indicazioni riportate in Scaffolding nei progetti ASP.NET Core per eseguire lo scaffolding IdentityPages\Manage\EnableAuthenticator nell'app.

Nota

Anche se solo il componente è selezionato per lo EnableAuthenticator scaffolding in questo esempio, lo scaffolding aggiunge attualmente tutti i Identity componenti all'app. Inoltre, le eccezioni possono essere generate durante il processo di scaffolding nell'app. Se si verificano eccezioni quando si verificano migrazioni di database, arrestare l'app e riavviare l'app in ogni eccezione. Per altre informazioni, vedere Eccezioni di scaffolding per Blazor l'app Web (dotnet/Scaffolding #2694).

Attendere l'esecuzione delle migrazioni. A seconda della velocità del sistema, il completamento delle migrazioni del database può richiedere fino a un minuto o due.

Per altre informazioni, vedere Scaffolding Identity nei progetti ASP.NET Core. Per indicazioni sull'uso dell'interfaccia della riga di comando di .NET anziché di Visual Studio, vedere comando dotnet aspnet-codegenerator.

Aggiunta di codici a matrice alla pagina di configurazione 2FA

Queste istruzioni usano il qrcode.js di Shim Sangmin: Generatore di codici a matrice tra browser per JavaScript (davidshimjs/qrcodejsrepository GitHub).

Scaricare la qrcode.min.js libreria nella wwwroot cartella del progetto server della soluzione. La libreria non ha dipendenze.

App Nel componente (Components/App.razor) inserire un riferimento allo script di libreria dopo Blazoril tag :<script>

<script src="qrcode.min.js"></script>

Il EnableAuthenticator componente, che fa parte del sistema di codice a matrice nell'app e visualizza il codice a matrice agli utenti, adotta il rendering statico lato server (SSR statico) con spostamento avanzato. Pertanto, gli script normali non possono essere eseguiti quando il componente viene caricato o aggiornato in una struttura di spostamento avanzata. Quando la pagina viene caricata, sono necessari passaggi aggiuntivi per attivare il codice a matrice da caricare nell'interfaccia utente. Per eseguire il caricamento del codice a matrice, viene adottato l'approccio descritto in ASP.NET Core Blazor JavaScript con rendering statico lato server (SSR statico).

Aggiungere l'inizializzatore JavaScript seguente alla cartella del wwwroot progetto server. Il {NAME} segnaposto deve essere il nome dell'assembly dell'app per Blazor individuare e caricare automaticamente il file. Se il nome dell'assembly dell'app server è BlazorSample, il file è denominato BlazorSample.lib.module.js.

wwwroot/{NAME}.lib.module.js:

const pageScriptInfoBySrc = new Map();

function registerPageScriptElement(src) {
  if (!src) {
    throw new Error('Must provide a non-empty value for the "src" attribute.');
  }

  let pageScriptInfo = pageScriptInfoBySrc.get(src);

  if (pageScriptInfo) {
    pageScriptInfo.referenceCount++;
  } else {
    pageScriptInfo = { referenceCount: 1, module: null };
    pageScriptInfoBySrc.set(src, pageScriptInfo);
    initializePageScriptModule(src, pageScriptInfo);
  }
}

function unregisterPageScriptElement(src) {
  if (!src) {
    return;
  }

  const pageScriptInfo = pageScriptInfoBySrc.get(src);
  
  if (!pageScriptInfo) {
    return;
  }

  pageScriptInfo.referenceCount--;
}

async function initializePageScriptModule(src, pageScriptInfo) {
  if (src.startsWith("./")) {
    src = new URL(src.substr(2), document.baseURI).toString();
  }

  const module = await import(src);

  if (pageScriptInfo.referenceCount <= 0) {
    return;
  }

  pageScriptInfo.module = module;
  module.onLoad?.();
  module.onUpdate?.();
}

function onEnhancedLoad() {
  for (const [src, { module, referenceCount }] of pageScriptInfoBySrc) {
    if (referenceCount <= 0) {
      module?.onDispose?.();
      pageScriptInfoBySrc.delete(src);
    }
  }

  for (const { module } of pageScriptInfoBySrc.values()) {
    module?.onUpdate?.();
  }
}

export function afterWebStarted(blazor) {
  customElements.define('page-script', class extends HTMLElement {
    static observedAttributes = ['src'];

    attributeChangedCallback(name, oldValue, newValue) {
      if (name !== 'src') {
        return;
      }

      this.src = newValue;
      unregisterPageScriptElement(oldValue);
      registerPageScriptElement(newValue);
    }

    disconnectedCallback() {
      unregisterPageScriptElement(this.src);
    }
  });

  blazor.addEventListener('enhancedload', onEnhancedLoad);
}

Aggiungere il componente condiviso PageScript seguente all'app server.

Components/PageScript.razor:

<page-script src="@Src"></page-script>

@code {
    [Parameter]
    [EditorRequired]
    public string Src { get; set; } = default!;
}

Aggiungere il file collocato seguente per il EnableAuthenticator componente, che si trova in Components/Account/Pages/Manage/EnableAuthenticator.razor.JS La onLoad funzione crea il codice a matrice con la libreria Sangmin qrcode.js usando l'URI del codice a matrice prodotto dal GenerateQrCodeUri metodo nel blocco del @code componente.

Components/Account/Pages/Manage/EnableAuthenticator.razor.js:

export function onLoad() {
  const uri = document.getElementById('qrCodeData').getAttribute('data-url');
  new QRCode(document.getElementById('qrCode'), uri);
}

<PageTitle> Nel componente del EnableAuthenticator componente aggiungere il PageScript componente con il percorso al file collocatoJS:

<PageScript Src="./Components/Account/Pages/Manage/EnableAuthenticator.razor.js" />

Nota

Un'alternativa all'uso dell'approccio con il PageScript componente consiste nell'usare un listener di eventi (blazor.addEventListener("enhancedload", {CALLBACK})) registrato in unJSafterWebStartedinizializzatore per ascoltare gli aggiornamenti delle pagine causati dalla navigazione avanzata. Il callback ({CALLBACK} segnaposto) esegue la logica di inizializzazione del codice a matrice.

Usando l'approccio di callback con enhancedload, il codice viene eseguito per ogni spostamento avanzato, anche quando non viene eseguito il rendering del codice <div> a matrice. È quindi necessario aggiungere codice aggiuntivo per verificare la presenza di prima di <div> eseguire il codice che aggiunge un codice a matrice.

Eliminare l'elemento <div> che contiene le istruzioni per il codice a matrice:

- <div class="alert alert-info">
-     Learn how to <a href="https://go.microsoft.com/fwlink/?Linkid=852423">enable 
-     QR code generation</a>.
- </div>

Individuare i due <div> elementi in cui deve essere visualizzato il codice a matrice e dove vengono archiviati i dati del codice a matrice nella pagina.

Apportare le modifiche seguenti:

  • Per l'oggetto vuoto <div>assegnare all'elemento un id oggetto .qrCode
  • Per con <div> l'attributo , assegnare all'elemento data-url un id oggetto di qrCodeData.
- <div></div>
- <div data-url="@authenticatorUri"></div>
+ <div id="qrCode"></div>
+ <div id="qrCodeData" data-url="@authenticatorUri"></div>

Modificare il nome del sito nel GenerateQrCodeUri metodo del EnableAuthenticator componente. Il valore predefinito è Microsoft.AspNetCore.Identity.UI. Modificare il valore in un nome di sito significativo che gli utenti possono identificare facilmente nell'app di autenticazione insieme ad altri codici a matrice per altre app. Lasciare codificato l'URL del valore. Gli sviluppatori impostano in genere un nome di sito che corrisponde al nome della società. Esempi: Yahoo, Amazon, Etsy, Microsoft, Zoho.

Nell'esempio seguente il {SITE NAME} segnaposto è il punto in cui il nome del sito (società):

private string GenerateQrCodeUri(string email, string unformattedKey)
{
    return string.Format(
        CultureInfo.InvariantCulture,
        AuthenticatorUriFormat,
-       UrlEncoder.Encode("Microsoft.AspNetCore.Identity.UI"),
+       UrlEncoder.Encode("{SITE NAME}"),
        UrlEncoder.Encode(email),
        unformattedKey);
}

Eseguire l'app e assicurarsi che il codice a matrice sia analizzabile e che il codice venga convalidato.

EnableAuthenticator componente nell'origine di riferimento

Il EnableAuthenticator componente può essere controllato nell'origine di riferimento:

EnableAuthenticator componente nell'origine di riferimento

Nota

I collegamenti della documentazione all'origine del riferimento .NET in genere caricano il ramo predefinito del repository, che rappresenta lo sviluppo corrente per la versione successiva di .NET. Per selezionare un tag per una versione specifica, usare l'elenco a discesa Switch branches or tags. Per altre informazioni, vedere How to select a version tag of ASP.NET Core source code (dotnet/AspNetCore.Docs #26205) (Come selezionare un tag di versione del codice sorgente di ASP.NET - dotnet/AspNetCore.Docs #26205).

Risorse aggiuntive