如何检查令牌过期和注销用户?

IT技术 javascript reactjs redux jwt redux-saga
2021-04-02 12:14:27

用户可以在他/她单击注销按钮时注销自己,但是如果令牌过期,他/她无法注销,因为在我的应用程序中,令牌用于服务器端和前端。当用户单击注销按钮时,如果令牌有效,则来自服务器和浏览器的令牌将被清除。有可能当用户没有注销并且他/她的令牌过期但没有在浏览器中被清除时。为了解决这种情况,我如何在用户每次访问我的应用程序时检查令牌是否过期,以便如果令牌已过期,请从浏览器中清除令牌?

我在 saga 中尝试过,每次用户刷新页面或切换到另一个页面时,它都会在后台观看。我不认为这是一种有效的方式。我认为中间件开始发挥作用。

function* loadInitialActions() {
  var dateNow = new Date();
  console.log(jwtDecode(token).exp < dateNow.getTime() - jwtDecode(token).iat);
  const token =
    JSON.parse(localStorage.getItem("user")) &&
    JSON.parse(localStorage.getItem("user"))["token"];
  if (
    token &&
    jwtDecode(token).exp < dateNow.getTime() - jwtDecode(token).iat
  ) {
    yield put(LOGOUT_SUCCESS);
  }
}

function* initialize() {
  const watcher = yield fork(loadInitialActions);
  yield take([INITIALIZE_ERROR, INITIALIZE_SUCCESS]);
  yield cancel(watcher);
}

function* rootSaga() {
  console.log("rootSaga");
  yield takeLatest(INITIALIZE, initialize);
}

所以我的问题是如果令牌从中间件过期,我如何使用令牌过期逻辑和注销用户?

3个回答

在我看来,中间件将是最好的选择。

你可以做这样的事情

const checkTokenExpirationMiddleware = store => next => action => {
  const token =
    JSON.parse(localStorage.getItem("user")) &&
    JSON.parse(localStorage.getItem("user"))["token"];
  if (jwtDecode(token).exp < Date.now() / 1000) {
    next(action);
    localStorage.clear();
  }
  next(action);
};

然后你必须把它包起来 applyMiddleware

@Tushant 我应该在哪里使用这个功能,authguard?
2021-05-23 12:14:27
您可以在 store.js 中使用它,并且该函数应该在 applyMiddleware() 中
2021-06-02 12:14:27
这就是我正在寻找的。它对我有用。非常感谢你的帮助。
2021-06-07 12:14:27
我正在使用 store.getState(token) 来获取令牌,并且我已经使用 redux-persist 将它持久化到本地存储中。但是当我调用它时它返回 null
2021-06-13 12:14:27
“1000”是毫秒吗?
2021-06-16 12:14:27

您需要使用 HOC 包装 Main 组件。HOC 将验证令牌,如果正常则允许组件显示。如果令牌无效,登录页面将被重定向到。

const authChecker = (Component) => {
  return class extends React.Component {
    state = {
      show: false;
    }

    componentWillReceiveProps(nextProps) {
      if (nextProps.children !== this.props.children) {
        this.checkAuth();
      }
    }

    componentDidMount() {
      this.checkAuth();
    }

    checkAuth() {
      Api.checkAuth()
      .then(result => {
        if (result.success) {
          this.setState({ show: true });
        } else {
          // logout since token expired
          API.logout();
        }
      });
    }

    render() {
      return this.state.show && <Component {...this.props} />
    }
  }
}

export default authChecker(Main);
检查中间件是另一种选择,也许更好。redux-oidc 包采用了这种方法。
2021-05-23 12:14:27
我感谢你的好意和帮助。我可以使用中间件,但我的令牌过期逻辑不起作用。我正在检查令牌是否已过期或未使用此条件,if (token && jwtDecode(token).exp < dateNow.getTime()) { next(action); localStorage.clear(); action.type = "Project/App/SHOW_TOKEN_INVALID_MESSAGE"; } 但使用此逻辑虽然我当前正在登录,但我已注销,因为它说我的令牌已过期。你能帮我解决使用 jwt-decode 的令牌过期逻辑吗?
2021-06-07 12:14:27
不是更好的方法是检查中间件吗?
2021-06-12 12:14:27

this.serverResponse.expires_in是以秒为单位的过期时间。

var tokenexpiration: Date = new Date();
tokenexpiration.setSeconds(new Date().getSeconds() + parseInt(this.serverResponse.expires_in))
console.log(tokenexpiration);

比您可以将其保存到 localStorage:

localStorage.setItem('expirationdate',tokenexpiration)

并且通过简单的条件,您可以在需要时检查令牌是否已过期。