为某些路由添加 MsalAuthenticationTemplate 导致所有路由都需要登录

问题描述

我有一个 ReactJS 网站,我在其中尝试使用“@azure/msal-react”:“^1.0.0-beta.1”,但遇到了一些让我感到困惑的问题。

  1. 我的大部分网页都对公众开放。有些需要登录。如果我添加如下 MSALAuthenticationTemplate(但使用交互类型 = 重定向),一旦我启动站点,它就会要求我登录。我认为只有当我点击 AuthenticationTemplate 中的路线时才会这样做。

  2. 使用 InteractionType Popup 会导致 SPA 在启动时抛出异常 错误:对象作为 React 子对象无效(找到:带有键 {login,result,error} 的对象)。如果您打算渲染一组子项,请改用数组。在 p(在 App.tsx:44)

  3. 出于某种原因,我的所有路由都返回主页而不是加载相关组件,AuthenticationTemplate 事件被注释掉。

我使用直接的 Javascript 进行了很多工作,但是在发布时遇到了 ESLint 问题,所以我认为 Typescript 可以帮助我解决这些问题。但现在它刚刚坏了。

render() {
        initializeIcons();

        return (
            <MsalProvider instance={msalClient} >
                <div className="d-flex flex-column h-100">
                    <TopMenu />

                    <div className="container-fluid flex-grow-1 d-flex">
                        <div className="row flex-fill flex-column flex-sm-row">

                            <browserRouter>
                                <MsalAuthenticationTemplate
                                    interactionType={InteractionType.Popup}
                                    errorComponent={this.ErrorComponent}
                                    loadingComponent={this.LoadingComponent}>
                                    <Switch>
                                        <Route path="/addevent">
                                            <AddEvent />
                                        </Route>
                                        <Route path="/mydashboard">
                                            <MyDashboard />
                                        </Route>
                                    </Switch>
                                </MsalAuthenticationTemplate >
                                <UnauthenticatedTemplate>
                                    <Switch>
                                        <Route path='/'>
                                            <Home />
                                        </Route>
                                        <Route path="/about">
                                            <About />
                                        </Route>
                                        <Route path="/contactus">
                                            <ContactUs />
                                        </Route>
                                        <Route path="/faq">
                                            <Faq />
                                        </Route>
                                        <Route path="/fetchevents">
                                            <FetchEvents />
                                        </Route>
                                        <Route path="/gettingstarted">
                                            <GettingStarted />
                                        </Route>
                                        <Route path="/partners">
                                            <Partners />
                                        </Route>
                                        <Route path="/privacypolicy">
                                            <PrivacyPolicy />
                                        </Route>
                                        <Route path="/sponsors">
                                            <Sponsors />
                                        </Route>
                                        <Route path="/termsofservice">
                                            <TermsOfService />
                                        </Route>
                                        <Route path="/userstories">
                                            <UserStories />
                                        </Route>
                                    </Switch>
                                </UnauthenticatedTemplate>
                                <div>
                                    <Footer />
                                </div>
                            </browserRouter>
                        </div>
                    </div>
                </div>
            </MsalProvider>
        );

解决方法

让我们从 UnauthenticatedTemplate 开始。如果用户通过身份验证,则组件的子组件将不会显示。所以我猜你不想在那里使用它。它的典型用法是例如登录/注销按钮。

另一个问题是,如果您使用 MsalAuthenticationTemplate 作为 SwitchRoute 组件的父级。问题是您正在保护未经身份验证的用户的开关和路由,但如果您不想保护整个页面,则这些组件应始终无需身份验证即可使用。

在渲染过程中,React 将一个接一个地遍历您的组件,它将尝试渲染的 BrowserRouter 组件的第一个子组件是 MsalAuthenticationTemplate,并且由于用户未通过身份验证,因此它将用户重定向到登录页面.

这是来自 react-router 文档的引用:

一个路由在技术上总是“渲染”的,即使它渲染为空。当 的路径与当前 URL 匹配时,它会呈现其子项(您的组件)。

因此,只有当路径被命中时,才会渲染路径的子级。所以你需要把 MsalAuthenticationTemplate 组件作为路由的直接子组件,甚至放在这样的组件中:

<Switch>
    <Route path="/addevent">
        <MsalAuthenticationTemplate
              interactionType={InteractionType.Redirect}
              authenticationRequest={loginRequest}
            >
            <AddEvent />
       </MsalAuthenticationTemplate>
    </Route>
    ...
</Switch>

对于重定向到主屏幕的所有网页,您应该在 Home 路由中添加 exact 关键字。此属性也导致它不匹配所有其他路由。单个“/”匹配所有其他路由。