【问题标题】:Authentication Refresh Token身份验证刷新令牌
【发布时间】:2017-11-08 16:57:38
【问题描述】:

使用 Reactjs、redux、axios 和 redux-thunk 构建登录表单。我有两个令牌 - 一个名为 access tokenrefresh token

当用户通过身份验证时,存储access token 应该持续 12 小时。还提供refresh token 并将持续 30 天。

一旦access token 已过期,如果access token 已过期,则需要检查时间戳(日期)。

access token 过期后如何更新?令牌数据看起来像这样,所以我有一个时间戳来检查:

{
  "access_token": "toolongtoinclude",
  "token_type": "bearer",
  "refresh_token": "toolongtoinclude",
  "expires_in": 43199,
  "scope": "read write",
  "roles": [
    "USER"
  ],
  "profile_id": "b4d1e37d-7d05-4eb3-98de-0580d3074a0d",
  "jti": "e975db65-e3b7-4034-a6e4-9a3023c3d175"
}

这是我从存储中保存、获取和更新令牌的操作。我只是不确定如何刷新令牌。

export function submitLoginUser(values, dispatch) {
    dispatch({type: constants.LOADING_PAGE, payload: { common: true }})
    return axios.post(Config.API_URL + '/oauth/token', {
            username: values.email,
            password: values.password,
            scope: Config.WEBSERVICES_SCOPE,
            grant_type: Config.WEBSERVICES_GRANT_TYPE_PASSWORD
        },
        {
            transformRequest: function (data) {
                var str = [];
                for (var p in data) {
                    str.push(encodeURIComponent(p) + '=' + encodeURIComponent(data[p]));
                }

                return str.join('&');
            },
            headers: {
                'Authorization': 'Basic ' + window.btoa(Config.WEBSERVICES_AUTH),
                'Content-Type': 'application/x-www-form-urlencoded'
            }
        })
        .then(response => {
            const {access_token, refresh_token} = response.data;
            dispatch({type: constants.LOADING_PAGE, payload: { common: false }})
            dispatch({
                type: constants.LOGIN_SUCCESS,
                payload: {
                    access_token: access_token,
                    refresh_token: refresh_token
                }
            });
            saveTokens(response)
            browserHistory.push('/questions');
            refreshToken(response);
        })
        .catch(error => {
            dispatch({type: constants.LOADING_PAGE, payload: { common: false }})
            //401 Error catch
            if(error.response.status === 401) {
              throw new SubmissionError({username: 'User is not authenticated', _error: message.LOGIN.loginUnAuth})
            }
            //Submission Error
            throw new SubmissionError({username: 'User does not exist', _error: message.LOGIN.loginFailed})
        })
}

/**
 * Save tokens in local storage and automatically add token within request
 * @param params
 */
export function saveTokens(params) {
    const {access_token, refresh_token} = params.data;
    localStorage.setItem('access_token', access_token);
    if (refresh_token) {
        localStorage.setItem('refresh_token', refresh_token);
    }
    //todo fix this later
    getinstanceAxios().defaults.headers.common['Authorization'] = `bearer ${access_token}`
}

/**
 *
 */
export function getTokens() {
    let accessToken = localStorage.getItem('access_token');
    return accessToken
}

/**
 * update the get requests
 */
export function updateTokenFromStorage() {
    const tokenLocalStorage = getTokens();
    getinstanceAxios().defaults.headers.common['Authorization'] = `bearer ${tokenLocalStorage}`;
}

/**
 * Refresh user access token
 */
export function refreshToken(dispatch) {
    //check timestamp
    //check access expired - 401

    //request new token, pass refresh token
    //store both new access and refresh tokens

}

【问题讨论】:

  • 为什么不为你的所有请求创建一个拦截器。这个拦截器会检查你的令牌是否仍然有效,你知道吗?如果没有,请发送到新路线或显示一些消息。
  • 感谢 Valter - 我将研究 axios 的拦截器。

标签: reactjs axios redux-thunk


【解决方案1】:

看看这个:

https://github.com/mzabriskie/axios#interceptors

我认为这可以帮助你。您拦截您的请求并进行验证。

编辑

这是我尝试在商店中用于测试的代码,但没有返回任何日志

import { createStore, applyMiddleware, compose } from 'redux'
import { devTools, persistState } from 'redux-devtools'
import axios from 'axios'
import Middleware from '../middleware'
import Reducer from '../reducers/reducer'
import DevTools from '../containers/DevTools'

let finalCreateStore

if (__DEVELOPMENT__ && __DEVTOOLS__) {

  finalCreateStore = compose(
   applyMiddleware.apply(this, Middleware),
   // Provides support for DevTools:
      DevTools.instrument(),
   // Optional. Lets you write ?debug_session=<key> in address bar to persist debug sessions
   persistState(getDebugSessionKey())
 )(createStore)
} else {
  finalCreateStore = compose(
   applyMiddleware.apply(this, Middleware)
 )(createStore)
}

function getDebugSessionKey() {
  // You can write custom logic here!
  // By default we try to read the key from ?debug_session=<key> in the address bar
  const matches = window.location.href.match(/[?&]debug_session=([^&]+)\b/)
  return (matches && matches.length > 0)? matches[1] : null
}

axios.interceptors.response.use((err) => {
    if (err.status === 401) {
        console.log('ACCESS TOKEN EXPIRED!');
    }
});


export const store = finalCreateStore(Reducer)

【讨论】:

  • 感谢这个 valter - 我只是对在哪里调用拦截器函数感到困惑?
  • 你有没有试过用看看能不能解决你的问题?尝试在您的 index.js 或您创建 Root 组件、存储等的地方添加。试试看它是否有效。尽管我认为这是一个好地方,但我们可以稍后再考虑。
  • 这是问题的一半 我不确定如何使用它,以前没用过 - 很抱歉,这很新。我正在查看我的商店 index.js 文件,想知道我可以写什么来测试它?
  • Valter - 请使用我商店中的更新代码查看对您答案的编辑。
  • 我看到了。这管用吗?每次请求都会调用 console.log 吗?
猜你喜欢
  • 2020-07-07
  • 2019-02-27
  • 2018-05-27
  • 1970-01-01
  • 1970-01-01
  • 2021-09-06
  • 2020-08-30
  • 2017-12-29
  • 1970-01-01
相关资源
最近更新 更多