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

时间:2020-05-01 17:04:34

标签: javascript reactjs firebase frontend next.js

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

我原本是在Firebase上使用它的,但现在再也没有了!现在,在下面单独设置身份验证。

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

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);
                }
            }
        });
});

因此,仅通过这个小示例,我当前发送请求的方式有问题吗? (是否认为登录使用请求的格式?)

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

干杯!

1 个答案:

答案 0 :(得分:4)

我在这里建议的是创建一个自定义钩子,该钩子使用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)

现在,您只需要将应用程序包装在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钩子和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])

  ...
}

您可以继续使用导航栏中的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>
  )
}

很显然,您可以根据自己的需要为我们更改此设置,但是所有这些都可以帮助您轻松地使用身份验证状态。