【问题标题】:React - How to check if JWT is valid before sending a post request?React - 如何在发送发布请求之前检查 JWT 是否有效?
【发布时间】:2018-03-07 05:39:40
【问题描述】:

另一个菜鸟问题。我正在使用 JWT 授权将我的用户登录到系统,获取令牌并将其保存在 localstorage 中,然后发送一个保存数据的发布请求(基本上它是一个大表单)。问题是,服务器在给定时间(20 分钟左右)后使令牌失效,因此,我的一些帖子请求返回 401 status。在发送发布请求之前如何验证(如果需要,显示登录提示)?我正在使用redux-form 制作我的表格。

P.S:我知道我应该使用动作创建器之类的,但我还是个新手,所以不太擅长这些东西。

这是我的身份验证:

export function loginUser(creds) {

const data = querystring.stringify({_username: creds.username, _password: creds.password});

let config = {
    method: 'POST',
    headers: { 'Content-Type':'application/x-www-form-urlencoded' },
    body: data
};

return dispatch => {
    // We dispatch requestLogin to kickoff the call to the API
    dispatch(requestLogin(creds));

    return fetch(BASE_URL+'/login_check', config)
        .then(response =>
            response.json().then(user => ({ user, response }))
        ).then(({ user, response }) =>  {
            if (!response.ok) {
                // If there was a problem, we want to
                // dispatch the error condition
                dispatch(loginError(user.message));
                return Promise.reject(user)
            } else {
                // If login was successful, set the token in local storage
                localStorage.setItem('id_token', user.token);
                let token = localStorage.getItem('id_token')
                console.log(token);
                // Dispatch the success action
                dispatch(receiveLogin(user));
            }
        }).catch(err => console.log("Error: ", err))
    }
}

这是POST 请求(我从redux-form 获取values 对象)

const token = localStorage.getItem('id_token');
const AuthStr = 'Bearer '.concat(token);

let headers ={
headers: { 'Content-Type':'application/json','Authorization' : AuthStr }
};

export default (async function showResults(values, dispatch) {
axios.post(BASE_URL + '/new', values, headers)
    .then(function (response) {
        console.log(values);
        console.log(response);
    })
    .catch(function (error) {
        console.log(token);
        console.log(values)
        console.log(error.response);
    });
});

P.P.S:如果有人对改进我的代码有任何建议,请随时发表评论。

【问题讨论】:

    标签: javascript reactjs login redux jwt


    【解决方案1】:

    可以通过两种方式检查 JWT 是否过期。首先,您必须安装 jsonwebtoken 包并在文件顶部需要它。此后,您可以按照以下方法在发送任何休息请求之前检查 JWT 过期时间。

    选项 1

    var isExpired = false;
    const token = localStorage.getItem('id_token');
    var decodedToken=jwt.decode(token, {complete: true});
    var dateNow = new Date();
    
    if(decodedToken.exp < dateNow.getTime())
        isExpired = true;
    

    选项 2

    const token = localStorage.getItem('id_token');
    jwt.verify(token, 'shhhhh', function(err, decoded) {
      if (err) {
        /*
          err = {
            name: 'TokenExpiredError',
            message: 'jwt expired',
            expiredAt: 1408621000
          }
        */
      }
    });
    

    检查该方法的错误。如果是 TokenExpiredError 则表示令牌已过期。

    【讨论】:

    • 您对解决方案 2 非常确定吗?这意味着前面将有密钥来检查令牌。然后看源码,可以找到并用它来生成valide token
    • @PiHomeServer 是的,实际上基于我回答的问题,并给出了两种修复方法。但话虽如此,我们仍然可以改进检查 JWT 过期的方式。
    • 我实际上没有遵循任何选项。正如 Pi Home Server 所说,这不是很安全,所以最终做了一些服务器端验证。不过谢谢。
    • @SamiaRuponti 在客户端解码 JWT 并非不安全。任何拥有您的 JWT 令牌的人都可以对其进行解码。您甚至可以使用在线解码器。这就是为什么您只存储不安全的信息,如用户 ID、到期日期等。方法一是可用的。方法2不是。
    • @SamiaRuponti 只是为了向您澄清 JWT 令牌。 JWT 令牌只是简单地进行 base64 编码,因此任何人都可以“解码”令牌以查看令牌中存在哪些声明。 jwt.io 这个网站是一个很好的探索资源。 JWT 的第三部分是签名,仅使用存储在服务器上的密钥进行签名和验证。密钥应该始终保持安全,但理论上您可以简单地检查 JWT 中的 exp(过期)标头,而无需与服务器通信。
    【解决方案2】:

    通过将 JWT 令牌中的 exp 属性与当前时间进行比较,这是一个使用 jwt-decode 库的解决方案。 (JWT 令牌只是一个 Base64 编码的字符串)

    • 安装 jwt-decode (npm install jwt-decode --save)

       let token = localStorage.getItem(TOKEN);
        let decodedToken = jwt_decode(token);
        console.log("Decoded Token", decodedToken);
        let currentDate = new Date();
      
        // JWT exp is in seconds
        if (decodedToken.exp * 1000 < currentDate.getTime()) {
          console.log("Token expired.");
        } else {
          console.log("Valid token");   
          result = true;
        }
      

    重要提示:jwt-decode 不会验证令牌,任何格式正确的 JWT 都可以被解码。您应该使用 express-jwt、koa-jwt、Owin Bearer JWT 等工具在服务器端逻辑中验证令牌。

    【讨论】:

    • 我认为这比接受的答案更有效。 jwt-decode 是由jsonwebtoken 的同一作者制作的,在接受的答案中提到了,如果你只打算从浏览器(客户端)访问decode(并且你必须)token,这个库就是为此目的而制作的。
    【解决方案3】:

    您还可以使用中间件来检查令牌是否已过期。如果令牌即将过期,您甚至可以更新令牌。例如,您可以执行如下所示的操作;

     export function jwtMiddleware({ dispatch, getState }) {
      return (next) => (action) => {
        switch (action.type) {
          case 'CHECK_AUTH_TOKEN' :
            if (getState().auth && getState().auth.token) {
              var tokenExpiration = jwtDecode(getState().auth.token).exp;
              var tokenExpirationTimeInSeconds = (tokenExpiration - moment(Math.floor(Date.now() / 1000)));
              if (tokenExpiration && tokenExpirationTimeInSeconds < 20) {
                history.push(i18next.t('translation:routes.auth.logout'));
              }
            }
          break;
          case 'UPDATE_AUTH_TOKEN' :
            if (getState().auth && getState().auth.token) {
              var tokenExpiration = jwtDecode(getState().auth.token).exp;
              var tokenExpirationTimeInSeconds = (tokenExpiration - moment(Math.floor(Date.now() / 1000)));
              if (tokenExpiration && tokenExpirationTimeInSeconds < 100 && tokenExpirationTimeInSeconds > 20) {
                if (!getState().auth.fetching) {
                  return dispatch(refreshAuthToken(getState().auth));
                }
              }
            }
          break;
          case 'REFRESH_AUTH_TOKEN_FAIL' :
            if (getState().auth && getState().auth.token) {
              return dispatch(removeAuthToken(getState().auth)).then(response => {
                history.push(i18next.t('translation:routes.auth.logout'));
              });
            }
          break;
          }
        return next(action);
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-08
      • 2011-05-07
      • 2020-05-17
      • 2010-12-10
      • 1970-01-01
      相关资源
      最近更新 更多