如何使用 redux-thunk 处理 Redux 应用程序中的失败身份验证状态?

How do I deal with failed auth statuses in a Redux app using redux-thunk?

当服务器从 React/Redux Express 应用程序中的身份验证中间件发回 401 身份验证失败状态时,我正在努力处理客户端中的响应。

简而言之,在加载仪表板时,我正在向受保护的路由发出请求:

router.route('/')
  .get(authenticate, controller.get)

Authenticate 是检查 JWT 令牌的中间件:

exports.authenticate = function(req, res, next) {
  const authorizationHeader = req.headers['authorization']
  let token

  if (authorizationHeader) {
      token = authorizationHeader.split(' ')[1]
  }

  if (token) {
    jwt.verify(token, config.secrets.jwt, (err, decoded) => {
      if (err) {
        logger.log(err)
        res.status(401).json({ error: 'Failed to authenticate' })
      } else {
        User.findById(decoded._id)
        .select('-password')
        .exec()
        .then(user => {
          if (!user) {
            res.status(404).json({ error: 'No such user.' })
          } else {
            req.currentUser = user
            next()
          }
        })
      }
    })
  } else {
    res.status(403).json({ error: 'No token provided.' })
  }
}

所以如果认证失败,返回的状态是401。我正在研究如何在中间件中优雅地处理401状态并且:

如前所述,我正在使用 thunk 中间件来处理异步操作(只是不知道如何处理 401 响应)

const configureStore = () => {
  const store = createStore(
    rootReducer,
    window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
    applyMiddleware(thunk)
  )
  return store
}

谢谢:)

更新 我想我可以在操作中使用 catch,然后查询 res.status 代码,然后清除令牌并将用户注销,但这似乎是重复的,我需要为每个需要的操作执行此操作身份验证。

有没有更简洁的方法?我在下面用来说明的代码:

export const fetchTransactions = () => dispatch => axios.get('/api/transactions')
  .then(transactions => {
    dispatch({
      type: FETCH_TRANSACTIONS,
      payload: transactions
    })
  }).catch(err => {
    if (err.status === 401) {
      localStorage.removeItem('mm-jwtToken')
      setAuthToken(false)
      dispatch(setCurrentUser({}))
    }
  })

最后我在 action creator 中处理了错误,捕获了错误,然后调用了一个 handleErr 函数:

  • 已删除本地存储令牌
  • 使用 false 调用了删除授权的函数 header
  • 返回了为了从 Redux 存储中删除用户而需要分派的操作。

    函数 handleErr (err) { 如果(err.status === 401){ localStorage.removeItem('mm-jwtToken') setAuthToken(假) return setCurrentUser({}) } }

    export const fetchTransactions = () => dispatch => axios.get('/api/transactions') .then(交易 => { 派遣({ 类型:FETCH_TRANSACTIONS, 有效载荷:交易 }) }, 错误 => { 调度(handleErr(错误)) })