javascript - Next.js 身份验证示例 - 基于身份验证的重新路由,环绕其他功能

标签 javascript reactjs firebase frontend next.js

我正在尝试使用 next.js 进行小型项目的身份验证。身份验证当前有效,但不允许我在导航栏中显示数据。

我最初将它与 firebase 一起使用,但现在不再使用了!现在在下面单独设置身份验证。

这是示例存储库,其中包含用于身份验证的 API 和 next.js,我正在尝试将它们集成在一起,以便使用用于 api 调用的 header 集进行登录和注销。

https://github.com/Hewlbern/example

只需获得基本的登录和注销功能,这样我就可以控制用户对我的网站的访问。我知道这真的很简单 - 只是很困惑如何使用 next.js 和应用程序的文档页面如何工作:S

我试图显示此 API 的输出表,并提供下载输出的 json(到 CSV 或其他格式)的能力。因此,在使用查询参数进行搜索后,并且仅在用户登录后的页面上使用该功能,才是重点:)

这是我正在使用的登录功能的示例。

import { useRef, useState } from 'react';
import React from 'react'
import PropTypes from 'prop-types'

import Layout from "../components/Layout";




export default function Login() {
  const emailRef = useRef<HTMLInputElement>(null);
  const passRef = useRef<HTMLInputElement>(null);
  const [message, setMessage] = useState<any>(null);
  async function handleLogin() {
    const resp = await fetch('http://localhost:3001/auth/login', {
      method: 'POST',
      headers: {
        'Content-Type': "application/x-www-form-urlencoded"
      },
      body: JSON.stringify({
        email: emailRef.current?.value,
        password: passRef.current?.value
      })
    });
    const json = await resp.json();
    setMessage(json);
  }

  return (
    <Layout>
      {JSON.stringify(message)}
      <input type="text" placeholder="email" ref={emailRef} />
      <input type="password" placeholder="password" ref={passRef} />
      <button onClick={handleLogin}>Login</button>
    </Layout>
  );
}

这是发布到此 API 请求

router.post('/login', (req, res) => {

// console.log(req.body)

    let email = req.body.email;
    let password = req.body.password;

    console.log(email,password)

    DatabaseService.GetUser(email).then(user => {
            if(user===null){
                res.sendStatus(404);
            }
            else{
                if(bcrypt.compareSync(password, user[0].password)) {
                    jwt.sign({user}, 'secretkey', { expiresIn: '30d' }, (err, token) => {
                        DatabaseService.SetSession(token,JSON.stringify(user[0].user_id)).then(inserted=>{
                            res.json({
                                token
                            });
                        });
                    });
                } else {
                    res.sendStatus(500);
                }
            }
        });
});

那么就这个小例子来说,我当前发送请求的方式有问题吗? (认为​​这是登录接受请求的格式?)

如果有人做过类似的事情或知道如何解决这些问题,我真的很感激:)

干杯!

最佳答案

我在这里建议创建一个自定义钩子(Hook),它利用 React 的 Context API 来“监视”身份验证状态的变化。然后将您的应用程序包装在该提供程序中,您将可以使用新的自定义 Hook 灵活地对该身份验证状态执行任何您想要的操作。

以下示例展示了使用 Firebase 进行身份验证时该自定义 Hook 的外观:

import React, { createContext, useContext, useState } from 'react'

import { auth } from './services' // this is just firebase.auth()

const UserContext = createContext()

export const UserProvider = ({ children }) => {
  const [user, setUser] = useState(undefined)

  auth.onAuthStateChanged(setUser)

  return <UserContext.Provider value={user}>{children}</UserContext.Provider>
}

export const useUser = () => useContext(UserContext)

现在您只需将您的应用程序包装在 UserProvider 中。

像这样:

import React, { StrictMode } from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter } from 'react-router-dom'

import App from './app'
import { UserProvider } from './hooks'

const rootElement = document.getElementById('root')
ReactDOM.render(
  <StrictMode>
    <BrowserRouter>
      <UserProvider>
        <App />
      </UserProvider>
    </BrowserRouter>
  </StrictMode>,
  rootElement
)

然后举个例子,假设您希望在使用记录后自动离开登录页面。如果用户已登录,您可以使用 useEffect Hook 和 useHistory Hook 导航到 /

像这样的事情就可以了:

import React, { useEffect } from 'react'
import { useHistory } from 'react-router-dom'

import { useUser } from './hooks'

const LoginPage = () => {
  const history = useHistory()
  const user = useUser() // user is undefined if not logged in

  useEffect(() => {
    if (user) { // will run the condition if user exists
      history.push('/')
    }

  }, [user])

  ...
}

您可以继续在导航栏中实际使用用户数据,如下所示:

import React from 'react'
import { Link } from 'react-router-dom'

import { useUser } from './hooks'

const NavBar = () => {
  const user = useUser()

  return (
    <div>
      {user ?
        <Link to="/profile">Welcome, {user.displayName}</Link> :
        <Link to="/login">Login</Link>
      }
    </div>
  )
}

显然,您可以根据自己的需要为我们更改此设置,但是所有这些应该让您了解如何以干净稳健的方式使用身份验证状态。

关于javascript - Next.js 身份验证示例 - 基于身份验证的重新路由,环绕其他功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61547114/

相关文章:

Android Firebase orderByChild 查询

javascript - 谷歌地理图表中不同的、有范围的颜色

javascript - Ghost 代码 Markdown block 中的行号

reactjs - react SSR : Prevent client side rendering of components which are rendered on the server

reactjs - react : How to filter events according to date

python - 模块未找到错误: No module named 'firebase'

javascript - Firebase 身份验证 : Manually detect if the current user has recently authenticated

javascript - Puppeteer:如何获取页面中发送/接收的总字节数

javascript - 如何使用javascript将字典列表中的数字字符串转换为整数?

javascript - 如何使用 Cypress 测试网页已禁用滚动?