最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Next.js Example Auth - re-routing based on auth, wrapping around other functions - Stack Overflow

programmeradmin2浏览0评论

I'm trying to use the next.js with authentication for a small project. The authentication currently works but doesn't allow me to show the data in my navbar.

I was using it with firebase originally BUT NOT ANYMORE!! Now have the authentication set up separately below.

This is the example repo, it has my API in it for auth and the next.js, which i'm trying to integrate together to have login and logout working with header's set for api calls.


Just getting the basic login and logout functionality, so I can control user access to my website. I know this is really simple - just quite confused how to do it with next.js with how document page an app works :S

I am trying to show a table of output from this API, and give the ability to download the outputed json (into a CSV or whatever). So having that available after a search with the query params, and only on a page after the user is logged in, is the point :)

Here's an example of the login functionality I'm using.

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

import Layout from "../ponents/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>
  );
}

This is posting to this api request

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

So just with this small example, hat's wrong with how I'm sending the requests currently? (thinking it's the format the login takes requests in?)

If someone has done something similar or knows how to solve these issues, I'd really appreciate it :)

Cheers!

I'm trying to use the next.js with authentication for a small project. The authentication currently works but doesn't allow me to show the data in my navbar.

I was using it with firebase originally BUT NOT ANYMORE!! Now have the authentication set up separately below.

This is the example repo, it has my API in it for auth and the next.js, which i'm trying to integrate together to have login and logout working with header's set for api calls.

https://github./Hewlbern/example

Just getting the basic login and logout functionality, so I can control user access to my website. I know this is really simple - just quite confused how to do it with next.js with how document page an app works :S

I am trying to show a table of output from this API, and give the ability to download the outputed json (into a CSV or whatever). So having that available after a search with the query params, and only on a page after the user is logged in, is the point :)

Here's an example of the login functionality I'm using.

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

import Layout from "../ponents/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>
  );
}

This is posting to this api request

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.pareSync(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);
                }
            }
        });
});

So just with this small example, hat's wrong with how I'm sending the requests currently? (thinking it's the format the login takes requests in?)

If someone has done something similar or knows how to solve these issues, I'd really appreciate it :)

Cheers!

Share Improve this question edited May 13, 2020 at 7:14 LeCoda asked May 1, 2020 at 17:04 LeCodaLeCoda 1,0367 gold badges46 silver badges90 bronze badges 8
  • 1 What is the specific issue here, is the auth not working correctly, do you need the logic to work with handling SignIn and Signup button – Shubham Khatri Commented May 5, 2020 at 16:06
  • Sure. I want authentication to work, so i can have the login and logout button at a navbar level, and i want to use a API for login and logout and user functionality, as in the github API link. – LeCoda Commented May 6, 2020 at 2:22
  • @ShubhamKhatri Updated the question, hope it makes it simpler to understand! – LeCoda Commented May 9, 2020 at 9:23
  • @MichaelHolborn make a sample project on github and share the link and also eloborate on you problem with current source code. – NiRUS Commented May 10, 2020 at 9:26
  • @Nirus Okay will do :) – LeCoda Commented May 10, 2020 at 12:22
 |  Show 3 more ments

1 Answer 1

Reset to default 7 +100

What I'd remend here is to create a custom hook which makes use of React's Context API in order to "monitor" the auth state changing. Then wrap you app in that provider and you'll have the flexibility do anything you want with that auth state using your new custom hook.

Here's an example of how that custom hook would look using a authentication with 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)

Now you just need to wrap your app in the UserProvider.

Like this:

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
)

Then as an example, let's say you wanted to automatically direct away from your Login page if the use is logged it. You could make use of the useEffect hook, and useHistory hooks to navigate to / if the user is logged in.

Something like this will do:

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

  ...
}

You could go on to actually use the user data in your navigation bar using something like this:

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">Wele, {user.displayName}</Link> :
        <Link to="/login">Login</Link>
      }
    </div>
  )
}

Obviously you can change this for us according to your own needs, but all this should get you going with how work with authentication state in a clean robust manner.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论