Next.js:在重定向到 Keycloak 登录页面之前阻止显示索引页面

Posted

技术标签:

【中文标题】Next.js:在重定向到 Keycloak 登录页面之前阻止显示索引页面【英文标题】:Next.js: prevent Showing index page before redirecting to Keycloak Login page 【发布时间】:2021-07-30 09:45:04 【问题描述】:

我一直在研究 Next.js 项目,该项目使用 Keycloak 进行身份验证。

我使用 '@react-keycloak/s-s-r' 库来实现前端身份验证。

这是我的 _app.js 代码(代码参考:https://github.com/react-keycloak/react-keycloak-examples/tree/master/examples/nextjs-app)

import cookie from 'cookie'
import * as React from 'react'
import type  IncomingMessage  from 'http'
import type  AppProps, AppContext  from 'next/app'

import  s-s-rKeycloakProvider, s-s-rCookies  from '@react-keycloak/s-s-r'

const keycloakCfg = 
  url: 'http://myauthurl/auth',
  realm: 'myrealm',
  clientId: 'myclientid',




interface InitialProps 
  cookies: unknown


function MyApp( Component, pageProps, cookies : AppProps & InitialProps) 
  const initOptions = 
    onLoad: 'login-required',
    checkLoginIframe: false
  

  return (
    <s-s-rKeycloakProvider
      keycloakConfig=keycloakCfg
      persistor=s-s-rCookies(cookies)
      initOptions=initOptions
    >
      <Component ...pageProps />
    </s-s-rKeycloakProvider>
  )


function parseCookies(req?: IncomingMessage) 
  if (!req || !req.headers) 
    return 
  
  return cookie.parse(req.headers.cookie || '')


MyApp.getInitialProps = async (context: AppContext) => 
  // Extract cookies from AppContext
  return 
    cookies: parseCookies(context?.ctx?.req),
  


export default MyApp

我的目标是将未经身份验证的用户重定向到 keycloak 登录页面。它通过添加“initOptions”来工作。但是,在重定向之前,应用程序会显示一秒钟的索引页面。

编辑: 在编写代码检查身份验证状态后,我设法为未登录的用户隐藏了组件。但是,登录成功后应用程序显示空白页面并且 keycloak 未定义。

import type  AppProps, AppContext  from "next/app";
import  s-s-rKeycloakProvider, useKeycloak  from "@react-keycloak/s-s-r";
import  Provider  from "urql";
import 
  keycloakConfig,
  initOptions,
  getPersistor,
  Keycloak,
 from "../libs/keycloak";
import  parseCookies  from "../libs/cookie";
import  useMemo  from "react";
import  createUrqlClient, s-s-rCache  from "../libs/urql";

interface Props extends AppProps 
  cookies: unknown;
  token?: string;


function MyApp( Component, pageProps, cookies, token : Props) 
  const urqlClient = useMemo(() => createUrqlClient(token), [token]);
  const keycloak = useKeycloak
  console.log(keycloak) //undefined after login success
  console.log(keycloak?.authenticated  ) //undefined after login success
  // s-s-r cache for urql
  if (pageProps?.urqlState) 
    s-s-rCache.restoreData(pageProps.urqlState);
  
  return (
    <s-s-rKeycloakProvider
      keycloakConfig=keycloakConfig
      persistor=getPersistor(cookies)
      initOptions=initOptions
    >
      <Provider value=urqlClient>
        keycloak?.authenticated && <Component ...pageProps /> 
      </Provider>
    </s-s-rKeycloakProvider>
  );


MyApp.getInitialProps = async (context: AppContext) => 
  const keycloak = Keycloak(context?.ctx?.req);

  return 
    cookies: parseCookies(context?.ctx?.req),
    token: keycloak.token,
  ;
;
export default MyApp;

【问题讨论】:

它必须等待几秒钟,因为它需要检查身份验证.. 你想要的行为是什么? @Someone 特别感谢您的回答!我希望的行为是如果用户输入 url (localhost:3000) -> 检查身份验证 -> 如果未登录则重定向到 keycloak 登录页面。正如我在问题中所说,重定向是可以的,但在显示登录页面索引页面之前稍微暴露。 身份验证检查是异步的,您需要时间检查。看看下面的答案。您可以替代使用keycloak?.authenticated ? &lt;CustomComponent /&gt; : null,这样它就不会显示任何内容 @Someone special 谢谢你的建议!我不想在身份验证之前显示任何页面,所以我尝试使用 keycloak?.authenticated ? :空。虽然 keycloak 是通过调用 useKeycloak() 声明的,但 keycloak 是未定义的。 您需要根据我正确提供的代码检查您的代码。这是因为keycloak?.authenticated 不会返回未定义的错误,因为它使用了可选链接 - developer.mozilla.org/en-US/docs/Web/javascript/Reference/… 【参考方案1】:

它必须等待几秒钟,因为它需要检查身份验证..您希望的行为是什么?

您可以在页面中使用useKeycloak 挂钩来显示您想要的行为(例如重定向到登录页面......)

const IndexPage = () => 
  const  keycloak  = useKeycloak<KeycloakInstance>()

  const loggedinState = keycloak?.authenticated ? (
    <span className="text-success">logged in</span>
  ) : (
    <span className="text-danger">NOT logged in</span>
  )

  const welcomeMessage =
    keycloak?.authenticated 
      ? `Welcome back!`
      : 'Welcome visitor. Please login to continue.'

  return (
    <Layout title="Home | Next.js + TypeScript Example">
      <h1 className="mt-5">Hello Next.js + Keycloak ?</h1>
      <div className="mb-5 lead text-muted">
        This is an example of a Next.js site using Keycloak.
      </div>

      <p>You are: loggedinState</p>
      <p>welcomeMessage</p>
    </Layout>
  )


export default IndexPage

来自https://github.com/react-keycloak/react-keycloak-examples/blob/master/examples/nextjs-app/pages/index.tsx的简化示例

【讨论】:

以上是关于Next.js:在重定向到 Keycloak 登录页面之前阻止显示索引页面的主要内容,如果未能解决你的问题,请参考以下文章

Next.js:在实现私有路由时,如何在重定向之前防止未经授权的路由/页面的闪烁?

根据角色将不同的用户重定向到 Keycloak 登录的不同页面

如何将角度应用程序从keycloak登录重定向到特定路线

为啥 Spring Boot 不会重定向到 403 上的 Keycloak 登录页面?

如果 keycloak 会话过期,我如何重定向到登录页面?

重定向到登录时的 Keycloak CORS 问题