Next.js Example Auth - 基于 auth 的重新路由,环绕其他功能

Mic*_*orn 7 javascript frontend firebase reactjs next.js

我正在尝试将 next.js 与身份验证一起用于一个小项目。身份验证目前有效,但不允许我在导航栏中显示数据。

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

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

https://github.com/Hewlbern/example
Run Code Online (Sandbox Code Playgroud)

只需获得基本的登录和注销功能,就可以控制用户对我网站的访问。我知道这真的很简单 - 只是很困惑如何使用 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>
  );
}
Run Code Online (Sandbox Code Playgroud)

这是发布到这个 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);
                }
            }
        });
});
Run Code Online (Sandbox Code Playgroud)

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

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

干杯!

Bar*_*yle 7

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

以下是使用 Firebase 身份验证的自定义钩子外观示例:

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)
Run Code Online (Sandbox Code Playgroud)

现在您只需要将您的应用程序包装在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
)
Run Code Online (Sandbox Code Playgroud)

然后作为一个例子,假设你想自动直接离开你的登录页面,如果使用被记录下来。如果用户登录,您可以使用useEffect钩子和useHistory钩子导航到/

像这样的事情会做:

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])

  ...
}
Run Code Online (Sandbox Code Playgroud)

您可以使用以下内容继续实际使用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>
  )
}
Run Code Online (Sandbox Code Playgroud)

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