在反应中使用 cookie 的客户端身份验证和受保护的路由

Posted

技术标签:

【中文标题】在反应中使用 cookie 的客户端身份验证和受保护的路由【英文标题】:Client side authentication and protected routes using cookies in react 【发布时间】:2019-07-10 13:21:16 【问题描述】:

我目前在我的应用程序中使用无状态 JWT 令牌进行身份验证。在客户端,我正在运行一个具有受保护路由的 React + Redux 应用程序。它是使用 HOC 实现的,它检查 jwt 令牌是否存在并允许基于它的路由。

我最近读到 localstorage 不是存储 JWT 令牌的好地方。因此,我转而在 cookie 中使用 jwt。

但问题是如何在使用 cookie 时在客户端实现受保护的路由。 我在 react 应用程序中使用 react-router-dom 进行路由。

【问题讨论】:

我认为您会使用 api 调用使用 cookie 来返回该用户的用户信息。该调用的结果将是更新的 redux 存储,这反过来将“保护”客户端路由。 我确实考虑过这种方法。但是每次您访问受保护的路由时,HOC 都必须调用 api 进行检查,并且在请求解决之前存在延迟。我不想在每个页面加载之前都显示一个加载器。 @uman 您只能在安装应用程序时执行一次。对于所有受保护的路由,我相信您也在验证后端的 API 调用(例如,当您挂载受保护的组件时,您调用 API 以获取该屏幕的仅授权数据),因此每当您收到 Unauthorized响应,您始终可以将用户重定向到正确的位置,甚至在此重定向期间一起清除 redux 存储。 【参考方案1】:

简单,只要使用 if else

应用程序.js
import  connect  from "react-redux";
import  Redirect, Route, Switch  from "react-router";
import "./App.css";
import Auth from "./Components/Pages/Auth/Auth";
import Logout from "./Components/Pages/Auth/Logout/Logout";
import  checkAuthStatus  from "./Components/store/actions";

function App(props) 
  useEffect(() => 
    props.checkAuthStatus(); // checking authentication status of user on each reload
  , []);

  // filtering routes based on the authentication state of user
  const getRoutes = () => 
    if (props.auth) 
      return <Switch>/* ...authenticated routes */</Switch>;
     else 
      // unauthenticated routes
      return (
        <Switch>
          <Route path="/auth" component=Auth />
          <Route path="/logout" component=Logout />
          <Redirect to="/auth" />
        </Switch>
      );
    
  ;
  console.log(props.error);
  return (
    <div className="App">
      
        <Suspense fallback=<div>loading...</div>>
          props.loading ? <div>Authenticating...</div> : getRoutes()
        </Suspense>
      
    </div>
  );


const mapStateToProps = (state) => 
  return 
    auth:
      state.login.data.token !== undefined && state.login.data.token !== null,
    loading: state.login.loading,
    error: state.login.error,
  ;
;

const mapDispatchToProps = (dispatch) => 
  return 
    checkAuthStatus: () => dispatch(checkAuthStatus()),
  ;
;

export default connect(mapStateToProps, mapDispatchToProps)(App);

actions.js

import  axiosInstance  from "../../Utility/axiosInstance";
import  getCookie  from "../../Utility/cookies";
import * as actionTypes from "./actionTypes";

export const loginStart = () => 
  return 
    type: actionTypes.LOGIN_START,
  ;
;
export const loginFailure = (error) => 
  return 
    type: actionTypes.LOGIN_FAILURE,
    error,
  ;
;
export const loginSuccess = (data) => 
  return 
    type: actionTypes.LOGIN_SUCCESS,
    data,
  ;
;

export const checkAuthStatus = () => 
  return (dispatch) => 
    dispatch(loginStart());
    let token = getCookie("token");
    axiosInstance
      .post("/checkauthstatus",  id: token )
      .then((res) => 
        console.log(res.data);
        dispatch(loginSuccess(res.data));
      )
      .catch((err) => 
        console.log(err);
        let error = "something went wrong";
        if (err.response) 
          error = err.response.message;
        
        dispatch(loginFailure(error));
      );
  ;
;

【讨论】:

以上是关于在反应中使用 cookie 的客户端身份验证和受保护的路由的主要内容,如果未能解决你的问题,请参考以下文章

从 Web Api 2 IAuthenticationFilter AuthenticateAsync 方法设置 cookie

OWIN - Authentication.SignOut() 似乎没有删除 cookie

httpOnly cookie 中的 JWT - AuthGuard 和受保护的路由(Node.js、Angular)

使用 redux 保护的路由和身份验证反应路由器 v4

用于反应前端的基于令牌的身份验证

React Redux with hooks - 身份验证和受保护的路由