保持 React 基于 Cookie 的身份验证状态

Posted

技术标签:

【中文标题】保持 React 基于 Cookie 的身份验证状态【英文标题】:Persist React Cookie-based Authentication state 【发布时间】:2020-09-16 04:17:18 【问题描述】:

我正在使用 React-Router 和 Redux 构建身份验证流程,其中我的后端以会话 Cookie(带有 Set-Cookie HTTP 标头)的形式返回 JWT,前端使用该 JWT 来发出后续请求。 (我没有使用 localStorage,因为一般建议是首选 Cookie,因为在 XSS 的情况下它可能被 JS 读取)

// my App component
  const  isAuthenticated  = useSelector((state) => state.user);

          <Container>
            !isAuthenticated ? (
              <LoginForm />
            ) : (
              <Switch>
                <Route exact path="/" component=MessageList />
                <Route path="/messages" component=MessageList />
                <Route path="/login" component=LoginForm />
                <Route path="/message/:id" component=MessageContainer />
              </Switch>
            )
          </Container>
// the api requests themselves abstracted
const login = (data) =>
  axios
    .post("auth/login", data,  withCredentials: true )
    .then((response) => response.data);

const fetchItems = (page, token) =>
  axios(`message/list/page/$page`, 
    withCredentials: true,
  ).then((response) => response.data);
// actions
function handleError(err) 
  return 
    type: "ERROR_OCCURED",
    payload: err,
  ;


function shouldFetchMessages(state, page) 
  if (!state.message.all.length) 
    return true;
   else if (state.message.isFetching) 
    return false;
   else 
    return state.message.all;
  


export let getMessages = (page = 1) => async (dispatch, getState) => 
  let err, response;

  dispatch(requestMessages(page));
  [err, response] = await to(api.fetchItems(page, getState().user.accessToken));
  if (err) 
    return handleError(err);
  
  return dispatch(receiveMessages(response));
;

export function getMessagesIfNeeded(page) 
  return (dispatch, getState) => 
    if (shouldFetchMessages(getState(), page)) 
      return dispatch(getMessages(page));
    
  ;

// reducer
// where would the localStorage isAuthenticated value be synced with the store?
export default (state = defaultState, action) => 
  switch (action.type) 
    // skipped the other reducers for brevity
    case "ERROR_OCCURED":
      return 
        ...state,
        isAuthenticated: false, // this should be saved in the localStorage
      ;
    default:
      return state;
  
;

我需要有一个BOOLEAN 来保存isAuthenticated 的“状态”,这样我才能显示适当的组件。

我的主要问题是 Redux 状态当然不会在页面刷新时保持不变。

我想有一个localStorage 变量,(或一个新的cookie)。 (包含 JWT 的 Cookie 是httpOnly,据我了解,javascript 无法访问)。

问题:

这是一种既定做法 如何处理 JWT 过期? (我想如果 HTTP 请求失败并返回 401,我可以将其设置为 false。) localStorage 变量在哪里与 Redux 状态同步以避免我的 Reducer 中的副作用?

【问题讨论】:

【参考方案1】:

我绝对不是这方面的专家,但在我的应用程序中,每当我设置或删除 httpOnly JWT cookie 时,我也会设置/删除一个常规 cookie,其中包含有关用户是否登录以及他们的角色的信息.然后,您可以在客户端检查一些内容,而不会暴露任何敏感内容。

【讨论】:

以上是关于保持 React 基于 Cookie 的身份验证状态的主要内容,如果未能解决你的问题,请参考以下文章

React Native - 在 WebView 中使用 cookie 进行身份验证

如何在 React/NodeJS 身份验证流程中使用 httpOnly cookie 获取用户数据

从cookie异步加载身份验证令牌时,React react-router-dom私有路由不起作用

关于Session和cookie个人见解

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

基于 Cookie 的身份验证