【问题标题】:How to define PrivateRoute in React.js which works only after authentication?如何在 React.js 中定义仅在身份验证后才有效的 PrivateRoute?
【发布时间】:2019-12-03 16:07:41
【问题描述】:

我有一个后端 API,我可以向其发送电子邮件和密码。作为回报,它会在成功认证后提供一个认证令牌。我已经在文件 auth.js 中编写了用于发送此 API 请求的代码。它看起来像这样:

import axios from "axios";

export const auth = {
  isAuthenticated: false,
  login(user) {
    const config = {
      headers: {
        "Content-Type": "application/json"
      }
    };
    const body = JSON.stringify({ email: user.email, password: user.password });
    return axios
      .post("http://localhost:5000/userauth/login", body, config)
      .then(res => {
        localStorage.setItem("token", res.data.token);
        this.isAuthenticated = true;

        return res.data;
      })
      .catch(err => {
        this.isAuthenticated = false;
        console.log(err);
      });
  }
};

我在 App.js 中调用 auth。在这个 I 文件中,我有一个私有路由“/dashboard”,只有在身份验证后才能访问。如果未通过身份验证,它会重定向到“/login”路由。

这是它的代码:

import { auth } from "./actions/auth";
// rest of imports ...

export default function App() {
  return (
    <Router>
      <Route path="/" exact component={Home} />
      <Route path="/login" component={Login} />
      <PrivateRoute path="/dashboard" component={Dashboard} />
    </Router>
  );
}
// ... ...
const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route
    {...rest}
    render={props =>
      auth.isAuthenticated === true ? (
        <Component {...props} />
      ) : (
        <Redirect to="/login" />
      )
    }
  />
);

另外,我的登录表单的 onSubmit 函数如下所示:

onSubmit(e) {
    e.preventDefault();
    const user = {
      email: this.state.email,
      password: this.state.password
    };

    auth.login(user).then(res => {
      if (res) {
        this.props.history.push("/dashboard");
      }
    });
  }

现在每当我在登录表单中输入正确的emailpassword 时,我都会成功重定向到/dashboard 路由。但是如果我在登录后重新加载/dashboard 路由,它会再次将我发送回登录页面。 据我了解,它应该留在仪表板页面上,因为登录后isAuthenticated 设置为 true。

因此我的私人路线应该有效。那我错过了什么?另外作为记录,我正在关注 this 创建 PrivateRoute 的教程。

【问题讨论】:

    标签: reactjs asynchronous react-router


    【解决方案1】:

    当您重新加载页面时,react 状态会丢失。

    登录成功时您已经保存了令牌。因此我们可以利用该令牌来恢复身份验证状态。

    只要您有令牌并且令牌尚未过期,用户就可以保持身份验证。

    要检查令牌是否过期,我们可以使用jwt-token 包。

    你可以像这样修改你的 auth.js 来完成这个:

    import axios from "axios";
    import jwt_decode from "jwt-decode";
    
    export const auth = {
      isAuthenticated: isValidToken(),
      login(user) {
        const config = {
          headers: {
            "Content-Type": "application/json"
          }
        };
        const body = JSON.stringify({ email: user.email, password: user.password });
        return axios
          .post("http://localhost:5000/userauth/login", body, config)
          .then(res => {
            localStorage.setItem("token", res.data.token);
            this.isAuthenticated = true; //we may remove this line if it works without it
    
            return res.data;
          })
          .catch(err => {
            this.isAuthenticated = false;
            console.log(err);
          });
      }
    };
    
    const isValidToken = () => {
      const token = localStorage.getItem("token");
    
      if (token && isValid(token)) {
        return true;
      }
    
      return false;
    };
    
    const isValid = token => {
      const decoded = jwt_decode(token);
    
      const currentTime = Date.now() / 1000;
    
      if (currentTime > decoded.exp) {
        return false;
      }
    
      return true;
    };
    

    【讨论】:

    • 谢谢。另外,我的 PrivateRoute 也有问题吗?我有一种强烈的感觉是不对的。
    • @TarunKhare 如果您正确地遵循了该教程,我认为没有理由认为私人路线不起作用。您能否将我的回答应用于您的应用并提供反馈?
    【解决方案2】:

    React 状态在刷新后重置。 您的问题是您的auth state 在刷新后正在重置。

    每次刷新页面时,您都应该确保自己 re-authenticate,理想情况下,您应该在 useEffect()componentDidMount() 的路由组件中执行此操作,具体取决于您使用的是钩子还是类。

    正如@Steve 所指出的,您可以从localStorage 获取令牌。

    【讨论】:

    • 我认为他们不需要在后端重新进行身份验证。他们已经将身份验证令牌设置为 localStorage。他们只需要在组件安装时抓住它。
    • 是的,我完全错过了那部分。我将编辑我的答案。谢谢@SteveK
    猜你喜欢
    • 2019-01-03
    • 2020-06-01
    • 2020-03-19
    • 2019-05-23
    • 2020-04-02
    • 2021-02-06
    • 2020-04-24
    • 2020-04-01
    • 2022-12-10
    相关资源
    最近更新 更多