0

所以我在完成我的 2FA 方法的最后一步,现在我需要检测用户是否启用了他的方法并实现这一点,我创建了一个返回以下内容的函数:

if (!user.twoFactorTokenEnabled) {
  // If user has not enabled twoFactorAuthentication, then
  // let him proceed and log in into his account
  sendTokenResponse(user, 200, req, res)
} else {
  // Otherwise, just return the following fields:
  // username, isEmailConfirmed and twoFactorTokenEnabled
  res.status(200).json({ success: true, data: user })
}

该功能位于后端,到目前为止它运行良好,或者至少这是我想要相信的。login话虽如此,我每次提交表单时都会进入我的登录组件并触发该功能:

const [TFAEEnabled, setTFAEnabled] = useState(false)

login(loginData, history)
  .then((result) => {
    // If twoFactorTokenEnabled is found to be true
    // then call this function and set it to true and then
    // display and extra field to enter
    // a google authenticator code
    setTFAEnabled(result.payload.data.twoFactorTokenEnabled)
  })
  .catch((err) => {
    setTFAEnabled(false)
    setError(true)
  })

// This is found within my returned component.
{
  TFAEEnabled && (
    <Form.Control
      type="text"
      placeholder="Authenticator Code"
      aria-label="2FA-CODE"
      aria-describedby="2FA-CODE-text"
      autoComplete="2FA-CODE"
      name="2FA-CODE"
      id="2FA-CODE"
      minLength="6"
      required
      // onChange={handleChange('2FA-CODE')}
      value="2FA Code"
    />
  )
}

在上面的代码中并试图展示我正在尝试完成的内容是“如果 X 为真,则仅显示此组件”。然而,该函数根本不完全工作,因为它总是最终调用第一个减速器类型,这是登录函数:

export const login = (loginData, history) => async (dispatch) => {
  try {
    const res = await api.post(`/auth/login`, loginData)

    if (!res.data.twoFactorTokenEnabled) {
      // if twoFactorTokenEnabled === false then let
      // the user log in into his account normally
      // without requiring a token provided by Y
      // authenticator app
      dispatch({
        type: LOGIN_SUCCESS,
        payload: res.data,
      })
      // Dispatch the rest of the user data
      dispatch(loadUser())
      //  and let him in
      history.push('/timeline')
    } else {
      // otherwise, if twoFactorTokenEnabled === true
      // return the previously mentioned data given by
      // the backend: username, isEmailConfirmed and
      // twoFactorTokenEnabled
      return dispatch({
        type: LOGIN_SUCCESS_REQUEST,
        payload: res.data,
      })
    }
  } catch (err) {
    const error = err.response.data.message
    const errors = err?.response?.data?.errors

    if (error) {
      dispatch(setAlert(error, 'danger'))
    }

    if (errors) {
      errors.forEach((error) => dispatch(setAlert(error.msg, 'danger')))
    }
    dispatch({
      type: LOGIN_FAIL,
      payload: { msg: err.response?.statusText, status: err.response?.status },
    })
  }
}

后端工作得很好!它返回了它应该返回的数据,我相信这个问题存在于我的减速器中,它是这样的:

// if twoFactorTokenEnabled === true
// call this reducer which should only return
// the 4 fields given by the backend
case LOGIN_SUCCESS_REQUEST:
  return {
    ...state,
    // ...payload,
    isAuthenticated: false,
    isTFAEnabled: payload,
    loading: false
  };
// Otherwise let the user in and return everything
case LOGIN_SUCCESS:
    return {
      ...state,
      ...payload,
      isAuthenticated: true,
      loading: false
    };

希望这足以解释,否则请随时请求更多信息。

谢谢!。

4

2 回答 2

0

我实际上发现我没有根据后端发送的内容返回数据,我必须在 if 语句中返回第二个“数据”:

const res = await api.post(`/auth/login`, loginData);

    if (res.data.data) {
      history.push(`/two-fa-validate/${res.data.data._id}`);
      return dispatch({
        type: LOGIN_SUCCESS_REQUEST,
        payload: res.data
      });
    }
    dispatch({
      type: LOGIN_SUCCESS,
      payload: res.data
    });
    dispatch(loadUser());
    history.push('/timeline');
于 2020-12-26T07:58:44.113 回答
0

我认为您正在使用 Redux-thunk 并且您需要调度您的操作函数。然后可以从 Redux 商店中选择 TFAEEnabled。

const TFAEEnabled = useSelector(state => state.isAuthenticated);
const dispatch = useDispatch();

dispatch(login(loginData, history));
于 2020-12-25T21:21:50.250 回答