简体   繁体   English

jwt 刷新令牌反应

[英]jwt refresh token react

I'm working on a small app that utilises JWT for authentication but I'm not sure how to refresh the token when it expires.我正在开发一个使用 JWT 进行身份验证的小型应用程序,但我不确定如何在令牌过期时刷新它。 My token expires after 15 mins, I've provided the details below about my api and how I'm using it.我的令牌在 15 分钟后过期,我在下面提供了有关我的 api 以及我如何使用它的详细信息。 I have a login which generates an access_token which will expire eventually and my data will disappear.我有一个登录,它会生成一个access_token ,它最终会过期,我的数据会消失。 how do I refresh the token?如何刷新令牌?

Heres what I have tried:这是我尝试过的:

On Login I've added the refresh token and the access_token to locale storage.在登录时,我已将refresh tokenaccess_token添加到区域设置存储中。 If you post a refresh token to the https://freddy.codesubmit.io/refresh api it returns an access_token ;如果您将刷新令牌发布到https://freddy.codesubmit.io/refresh api 它会返回一个access_token but this hasn't worked.但这没有奏效。

const refreshToken = getItem('refresh_token')

useEffect(() => {
if(response === null) {
  axios.post('https://freddy.codesubmit.io/refresh', {}, {headers: {Authorization: `Bearer ${refreshToken}`}})
   .then(res => {
    localStorage.setItem("token", res.data.access_token);
  })
  .catch(err => console.log(err))
}
}

details on jwt api: jwt api 的详细信息:

Retrieve the necessary data for the dashboard at 'https://freddy.codesubmit.io/dashboard'. 
This endpoint requires a 'Authorization: Bearer access_token' header. 
Use the access token that you retrieved from Login. 
Keep in mind that access tokens expire after 15 minutes. 
You may request a fresh access token by sending a POST request to https://freddy.codesubmit.io/refresh' 
with the 'Authorization: Bearer refresh_token' header.

I haven't done the refresh token part yet as I'm not sure how to, I assume that may be the problem?我还没有完成刷新令牌部分,因为我不知道该怎么做,我认为这可能是问题所在? Its timing out because the token is expired?由于令牌过期而超时?

Here is my login:这是我的登录信息:

import React, {useContext, useState} from 'react';
import { useHistory } from 'react-router-dom'
import axios from 'axios';
import { AuthContext } from '../hooks/UserContext';
import Logo from '../images/Freddys_Logo.svg';
import '../css/Login.css';
  
const Login = () => {
  const [userError, setUserError] = useState("");
  const [passError, setPassError] = useState("");
  const {setLoggedIn} = useContext(AuthContext);
  let history = useHistory();
  const [authInfo, setAuthInfo] = useState({
    username: "",
    password: ""
  })

  const handleChange = e => {
    setAuthInfo({
      ...authInfo,
      [e.target.name]: e.target.value
    })
  }

  const handleSubmit = e => {
    e.preventDefault();
    axios.post('https://freddy.codesubmit.io/login', authInfo)
      .then(res => {
        setLoggedIn(true);
         localStorage.setItem("token", res.data.access_token);
         localStorage.setItem("refresh_token", res.data.refresh_token);
         history.push('/dashboard')
      })
      .catch(err => console.log(err))
  }

 return (
  <div className="wrapper">
    <div className="logoContainer">
    <div className="heading">
       <p>
         Freddy's
         <br/>
        Artisanal
        <br/>
        Halloween
        <br/>
        Candy Shop
       </p>
    </div>
      <div className="svgLogo">
        <img src={Logo} className="svgLogo" alt="image" />  
      </div>
    </div>
    <div className="inputContainer">
    <form method="POST" onSubmit={handleSubmit}>
      <input 
        name="username" 
        type="text" 
        value={authInfo.username} 
        placeholder="username" 
        onChange={handleChange} 
        className="input" 
      />
      <input 
        name="password" 
        type="password" 
        value={authInfo.password} 
        placeholder="************" 
        onChange={handleChange}  
        className="input" 
      />
      <input 
        type="submit"  
        value="Login" 
        className="submitButton"
      />
    </form>
    </div>
  </div>
 )
}

export default Login;

Here is my api I'm using to grab my data: useFetch.js这是我用来获取数据的 api:useFetch.js

import { useEffect, useState } from "react";
import axios from "axios";
const useFetch = async => {
  const [response, setResponse] = useState(null);
  const [error, setError] = useState(null);

  const token = localStorage.getItem("token");

  useEffect(() => {
    async function fetchData() {
      try {
        const res = await axios.get(
          "https://freddy.codesubmit.io/dashboard"
        , {headers: {Authorization: `Bearer ${token}`}});

        setResponse(res);
      } catch (error) {
        setError(error, "err");
      }
    }

    fetchData();
  }, [token]);
  return { response, error };
};
export default useFetch;

Here is the page I'm trying to display my data on: Dashboard.jsx这是我试图在其上显示数据的页面:Dashboard.jsx

import React, {useState, useContext, useEffect} from 'react';
import Layout from './Layout';
import Table from './Table';
import axios from 'axios';
import { useHistory } from 'react-router-dom'
import { AuthContext } from '../hooks/UserContext'
import useFetch from "../hooks/useFetch";
import Switch from "react-switch";
import BarChart from 'react-bar-chart';

import '../css/Dashboard.css'

const Dashboard = () => {
  const {} = useContext(AuthContext);
  const { response, error } = useFetch();
  const [checked, setChecked] = useState(false);
  const refreshToken = localStorage.getItem("refresh_token")


  const handleCheckedChange = () => {
    setChecked(!checked)
  }

  const lastSevenDays = [
    {text: 'yesterday', value: 500}, 
    {text: 'today', value: 1300},
    {text: 'day 3', value: 300},
    {text: 'day 4', value: 300}, 
    {text: 'day 5', value: 300},
    {text: 'day 6', value: 300}, 
    {text: 'day 7', value: 300}, 
  ];
  const lastTwelveMonths = [
    {text: 'this month', value: 500}, 
    {text: 'today', value: 1300},
    {text: 'day 3', value: 300},
    {text: 'day 4', value: 300}, 
    {text: 'day 5', value: 300},
    {text: 'day 6', value: 300}, 
    {text: 'day 7', value: 300}, 
  ];
  const margin = {top: 10, right: 20, bottom: 30, left: 40};

  console.log(error)

 return (
    <Layout>
        <h1>Dashboard</h1>
        <div className="container">
          <div className="item">
            <span className="textStyle">Today</span>
            <p>$1456 / 9 orders</p>
          </div>
          <div className="item">
            <span className="textStyle">Today</span>
            <p>$1456 / 9 orders</p>
          </div>
          <div className="item">
            <span className="textStyle">Today</span>
            <p>$1456 / 9 orders</p>
          </div>
        </div>

        <div className="revenueContainer">
          <div className="title">
          {!checked ? <h2>Revenue (last 7 days)</h2> : <h2>Revenue (last 12 months)</h2>}
          </div>
          <div className="toggle">
            <Switch 
              onChange={handleCheckedChange} 
              checked={checked} 
              onColor="#86d3ff"
              onHandleColor="#2693e6"
              uncheckedIcon={false}
              checkedIcon={true}
              boxShadow="0px 1px 5px rgba(0, 0, 0, 0.6)"
              activeBoxShadow="0px 0px 1px 10px rgba(0, 0, 0, 0.2)"
            />
          </div>
        </div>

        <div>
            <div style={{width: '100%'}}> 
            {!checked ? (
              <BarChart 
                ylabel=''
                width={600}
                height={300}
                margin={margin}
                data={lastSevenDays}
              />
              ) : !!checked ? (
                <BarChart 
                ylabel=''
                width={600}
                height={300}
                margin={margin}
                data={lastTwelveMonths}
              />
              ) : null}
            </div>
          </div>

        <h2>Bestsellers</h2>
        <Table bestsellers={response?.data.dashboard.bestsellers} /> 
    </Layout>
 )
}

export default Dashboard;

Table component in Dashboard.js Dashboard.js 中的表格组件

import React from 'react';
import '../css/Table.css';

const Table = ({bestsellers}) => {
  if(bestsellers === undefined || null) {
    return <div> loading...</div>
  }
  return (
    <div className="tableContainer">
      <div className="headingContainer">
        <div className="tableHeader"><span className="tableHeading">Product Name</span></div>
          <div className="tableHeader"><span className="tableHeading">Price</span></div>
          <div className="tableHeader"><span className="tableHeading"># Units Sold</span></div>
          <div className="tableHeader"><span className="tableHeading">Revenue</span></div>
      </div>
      {bestsellers
         .slice(0, 3)
         .map(row => (
        <div className="rowContainer" key={row.product.id}> 
          <div className="tableItem">
            <span className="tableItemText">{row.product.name}</span>
          </div>
          <div className="tableItem">
            <span className="tableItemText">N/A</span>
          </div>
          <div className="tableItem">
            <span className="tableItemText">{row.units}</span>
          </div>
          <div className="tableItem">
            <span className="tableItemText">{row.revenue}</span>
          </div>
        </div>
      ))}
    </div>
  )
}

export default Table;

Just set a timeout of less than 15 minutes, at the moment of authorization, with a callback of sending a request with a refresh token.只需在授权时设置小于 15 分钟的超时时间,并回调发送带有刷新令牌的请求。 Then, after getting the fresh one, swap the auth_tokens.然后,在获得新的之后,交换 auth_tokens。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM