Výkonnost v MSAL React

Jak nakonfigurovat @azure/msal-react, aby používal navigační funkci vašeho routeru pro navigaci na straně klienta

Pokud MSAL.js ve výchozím nastavení potřebuje přejít z jedné stránky v aplikaci na jinou, znovu se přiřadí window.location, což způsobí přesměrování celého rámce na druhou stránku a způsobí opětovné vykreslení aplikace. Pokud používáte směrovač, může to být nepopiratelné, protože mnoho směrovačů poskytuje metodu, pomocí které můžete provést navigaci na straně klienta a znovu vykreslit jenom části stránky, které je potřeba znovu vykreslit.

V současné době existuje jeden scénář, kdy MSAL.js přejde z jedné stránky v aplikaci na jinou. Pokud vaše aplikace provádí všechny následující věci, pokračujte ve čtení:

  • Vaše aplikace k přihlášení používá tok přesměrování místo automaticky otevíraného toku.
  • PublicClientApplication je nakonfigurovaný s auth.navigateToLoginRequestUrl: true (výchozí)
  • Vaše aplikace má stránky, které mohou volat loginRedirect/acquireTokenRedirect se sdíleným redirectUri; to znamená, že voláte loginRedirect z http://localhost/protected s redirectUri http://localhost

Pokud vaše aplikace splňuje vše uvedené výše, můžete přepsat metodu, kterou Msal používá pro navigaci, vytvořením vlastní implementace INavigationClient a zavoláním setNavigationClient na instanci PublicClientApplication před vykreslením MsalProvider.

Poznámka: Doporučujeme, aby se MsalProvider vykresloval nad komponentami Route a aby funkce navigateInternal vracela false. Když navigateInternal vrátí hodnotu false, tokeny se zpracují okamžitě po navigaci. Pokud je MsalProvider znovu vykreslen v důsledku navigace, vaše funkce navigateInternal by měla vrátit true, aby se tokeny zpracovaly jako součást opětovného vykreslení.

Příklad implementace

Každý router má vlastní způsob, jak provádět navigaci na straně klienta, a v závislosti na tom, jak tuto metodu zpřístupňuje, možná budete muset refaktorovat svou aplikaci, aby tuto funkci podporovala. Následující příklad ukazuje, jak to implementovat pro react-router-dom. Můžete najít úplné ukázkové aplikace, které tuto implementaci implementují pro react-router-dom, Next.js a Gatsby.

Tyto ukázky uvedené výše využívají verzi react-router-dom 6. Pokud chcete místo toho použít react-router-dom v5, přečtěte si prosím: react-router-sample.

Implementace INavigationClient

import { NavigationClient } from "@azure/msal-browser";

/**
 * Extending the default NavigationClient allows you to overwrite just navigateInternal while continuing to use the default navigateExternal function
 * If you would like to overwrite both you can implement INavigationClient directly instead
 */
class CustomNavigationClient extends NavigationClient{
    constructor(navigate) {
        super();
        this.navigate = navigate // Passed in from useNavigate hook provided by react-router-dom;
    }
    
    // This function will be called anytime msal needs to navigate from one page in your application to another
    async navigateInternal(url, options) {
        // url will be absolute, you will need to parse out the relative path to provide to the history API
        const relativePath = url.replace(window.location.origin, '');
        if (options.noHistory) {
            this.navigate(relativePath, {replace: true});
        } else {
            this.navigate(relativePath);
        }

        return false;
    }
}

Poskytnutí vlastního navigationClient pro @azure/msal-browser

import { MsalProvider } from "@azure/msal-react";
import { BrowserRouter as Router , Routes, Route, useNavigate } from "react-router-dom";

function App({ msalInstance }) {
    // It's important that the Router component is above the Example component because you'll need to use the useHistory hook before rendering MsalProvider
    return (
        <Router>
            <Example msalInstance={msalInstance}/>
        </Router>
    );
};

function Example({ msalInstance }) {
    const navigate = useNavigate();
    const navigationClient = new CustomNavigationClient(navigate);
    msalInstance.setNavigationClient(navigationClient);

    return (
        <MsalProvider instance={msalInstance}>
            <Routes>
                <Route path="/protected" element={<ProtectedRoute />} />
                <Route path="/" element={<Home />} />
            </Routes>
        </MsalProvider>
    )
}