有时使用授权标头进行react-native fetch返回401

时间:2018-05-12 17:39:35

标签: laravel react-native laravel-5

我面临一些问题,我有时会从手机上获取状态码401(未经授权)。我尝试从我的计算机localhost(192.168.0.7)访问API。

我有一个屏幕,当我点击一个按钮时,它会导航到一个页面,它将通过API请求数据。当我再次返回并导航到同一页面时,有时会返回代码401。

因此,如果我重复相同的步骤(导航并返回),请说10次。我被解雇了5-7次。

以下是我的代码

export function getMyCarpool(param,token) {
    return dispatch => {   
        var requestUrl = _api + 'GetMyProduct?' + param;
        fetch(requestUrl, {
            method: "get",
            headers: new Headers({
                'Accept': 'application/json',
                'Content-Type': 'application/x-www-form-urlencoded',
                'Authorization': 'Bearer ' + token
            })
        })
        .then((request) => {
            console.log(request);
            if(request.status == 200)
                return request.json();
            else if(request.status == 401) {
                //dispatch(logout());    
                throw new Error('Unauthorized access.');
            }
            else 
                throw new Error('Failed to request, please try again.');
        })
        .then((response) => {
            var message = response.message;
            if(response.success == 'true') 
                dispatch({ message, type: GET_MY_PRODUCT_SUCCESS });
            else
                dispatch({ message, type: GET_MY_PRODUCT_FAILED });
        })
        .catch(error => { 
            var message = error.message;
            dispatch({ message, type: GET_MY_PRODUCT_FAILED }); 
        });
    }

我已经检查了手机中的令牌,并尝试使用邮递员提出许多请求。所以我不认为它是服务器方面的问题。

我使用Laravel并使用laravel passport进行API身份验证。我不确定如果我继续访问很多时间会发生这种情况,我们非常感谢任何帮助。

更新::我试图捕获http请求是否具有来自此link的令牌,我不再解决问题。

1 个答案:

答案 0 :(得分:0)

它是令牌过期的健康机制。也许您的令牌(access_token)持续5分钟,然后令牌已过期,您应该使用refresh_token重新获得另一个新令牌(access_token)

代码说明:

async function fetchService(url) {
  const reqSetting = {
    headers: {
      Accept: 'application/json',
      Authorization: `Bearer ${Auth.access_token}`,
    },
  };
  const prevRequest = { url, reqSetting };
  const resp = await fetch(url, reqSetting);
  if (!resp.ok) {
    const error = new Error(resp.statusText || 'Request Failed!');
    if (resp.status === 401 || resp.status === 400) {
      const responseClone = resp.clone();
      const errorInfo = await resp.json();
      if (errorInfo.error == 'invalid_token') {
        // console.log('Token Expired', errorInfo);
        try {
          await refreshToken();
          const response = await fetchService(prevRequest.url);
          return response;
        } catch (err) {
          // handle why not refresh a new token
        }
      }
      return responseClone;
    }
    error.errorUrl = url;
    error.code = resp.status;
    throw error;
  }
  return resp;
}

刷新令牌功能是:

async function refreshToken() {
  const url = 'https://example.com/oauth/token';
  const data = {
    grant_type: 'refresh_token',
    refresh_token: Auth.refresh_token,
  };
  try {
    const res = await fetch(url, data);
    const data = res.json();
    Auth.access_token = data.access_token;
    Auth.refresh_token = data.refresh_token;
    return true;
  } catch (error) {
    throw error;
  }
}

如果旧的fetchService过期,则fetchService将自动重新获得新令牌,然后处理旧请求。

PS。 如果您同时有多个请求,mongo: DB: database COL: collection log: error: log/error/error.log api: key: jhgwewbcjwefwjfg 将需要一些优化。您最好选择另一种重新获得令牌策略,例如saga