关于refresh token的总结

这两天做项目,第一次做了刷新token的功能。

以前做的最多的是:用户登录,给一个固定的token,并且这个token有一个期限。如果该token过期。那么持有该token的用户再次发起请求时,将会收到拒绝,并且前端页面给出“您的登录已过期”的提示,并跳转至登录页面。用户只能重新输入账号密码进行登录,然后再继续进行刚刚的操作。

我们可以看到,不由分说地将已过期的用户退出登录,是不科学和不人性化的。那么如何做才能比较好的进行token的管理呢?

我们引入refresh_token,可以比较好的解决这个问题。

首先明确一个前提:access_tokenrefresh_token两者都各自有一个期限,

我们假设access_token的期限是1小时,refresh_token的期限是2小时。

access_token过期后,我们不会像之前一样,直接让该用户退出登录。而是转而判断该用户的refresh_token的期限是否也过期。

如果refresh_token也过期了,那么该用户即可退出登录。

如果没有过期,此时应再次发起一个刷新access_tokenrefresh_token的请求,该请求会返回2个新的token,2个新token又各自有1个小时和2个小时的期限。

我们前端在拿到新的access_tokenrefresh_token后,重新将存在cooies中的2个token进行更新,并使用新的access_token再次发起刚刚失败的请求。这样在用户没有感知的情况下,将用户的token进行了“更新换代”的操作。

比较核心的代码如下(vue项目,使用ElementUI):

// 重新获取token 并将未完成的请求继续完成
async function doRequest (error) {
  const data = await store.dispatch('user/refreshToken')
  if (data) {
    const { access_token } = data
    const config = error.response.config
    config.headers.Authorization = 'Bearer ' + access_token
    const res = await axios.request(config)
    return res
  }
}
  // token过期后 刷新token
  refreshToken({ commit }) {
    return new Promise((resolve, reject) => {
      const params = {
        grant_type: 'refresh_token',
        refresh_token: getRefreshToken()
      }
      axios({
        url: `${baseUrl}auth/oauth/token`,
        method: 'post',
        params: params,
        headers: {
          isToken: false,
          Authorization: 'Basic b2E6MQ=='
        }
      }).then(res => {
        const { data } = res
        commit('SET_TOKEN', data.access_token)
        commit('SET_REFRESH_TOKEN', data.refresh_token)
        setToken(data.access_token)
        setRefreshToken(data.refresh_token)
        resolve(data)
      }).catch(error => {
        MessageBox.alert('请重新登录!', '登录已过期', {
          confirmButtonText: '确定',
          type: 'warning',
          callback: action => {
            store.dispatch('user/resetToken').then(() => {
              location.reload()
            })
          }
        })
        reject(error)
      })
    })
  },
### refresh token 的实现方式及流程 在现代身份验证体系中,`refresh token` 是一种用于重新获取有效 `access token` 的机制。以下是关于如何通过 `refresh token` 实现 `token` 刷新的具体方法及其工作流程: #### 1. 基本概念 - **Access Token**: 通常是一个短生命周期的令牌,客户端可以使用它来访问受保护资源[^1]。 - **Refresh Token**: 通常是长生命周期的令牌,允许客户端在不重新登录的情况下获得新的 `access token`。 #### 2. 工作原理 当用户的 `access token` 即将过期时,客户端可以通过发送有效的 `refresh token` 来向授权服务器请求一个新的 `access token`。在此过程中,服务器可能会返回一个新的 `refresh token` 或继续沿用旧的 `refresh token`,具体取决于配置和安全策略[^2]。 #### 3. 请求过程 以下是基于 OAuth 2.0 标准的一个典型刷新流程: ##### (a) 客户端准备 客户端需要保存两个重要数据: - 当前的有效 `refresh token` - 授权服务器地址(即 `/token` 端点) ##### (b) 发送请求 客户端向授权服务器发出 POST 请求,传递必要的参数。以下是一个标准的 HTTP 请求示例: ```http POST /oauth/token HTTP/1.1 Host: authorization-server.com Content-Type: application/x-www-form-urlencoded grant_type=refresh_token&client_id=your_client_id&client_secret=your_client_secret&refresh_token=existing_refresh_token ``` 其中: - `grant_type`: 设置为 `refresh_token` 表明这是一个刷新请求。 - `client_id` 和 `client_secret`: 应用程序的身份凭证。 - `refresh_token`: 需要使用的现有 `refresh token`。 ##### (c) 服务端处理 授权服务器接收到请求后会执行以下操作: 1. 验证传入的 `refresh token` 是否合法且未被吊销。 2. 如果合法,则生成并返回一个新的 `access token` 及可能的新 `refresh token`。 ##### (d) 返回响应 如果一切正常,服务器将以 JSON 格式返回如下结构的数据: ```json { "access_token": "new_access_token", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "optional_new_refresh_token" } ``` 字段说明: - `access_token`: 新生成的短期令牌。 - `token_type`: 令牌类型,一般为 Bearer。 - `expires_in`: 访问令牌有效期(秒数)。 - `refresh_token`: (可选)新生成的长期令牌。 #### 4. 安全注意事项 为了防止恶意攻击者滥用 `refresh token`,应采取以下措施: - 使用 HTTPS 加密通信以保障传输安全性。 - 对 `refresh token` 设定合理的生存周期,并定期轮换。 - 在检测到异常行为时立即撤销对应的 `refresh token`[^3]。 --- ### 示例代码 下面是一段简单的 Python 脚本演示如何利用 `requests` 库完成一次 `refresh token` 请求: ```python import requests def refresh_tokens(refresh_token, client_id, client_secret): url = 'https://authorization-server.com/oauth/token' payload = { 'grant_type': 'refresh_token', 'client_id': client_id, 'client_secret': client_secret, 'refresh_token': refresh_token } response = requests.post(url, data=payload) if response.status_code == 200: tokens = response.json() return tokens['access_token'], tokens.get('refresh_token') else: raise Exception(f"Failed to refresh token: {response.text}") # Example usage try: new_access_token, new_refresh_token = refresh_tokens( refresh_token='old_refresh_token', client_id='app_client_id', client_secret='app_client_secret' ) print("New Access Token:", new_access_token) except Exception as e: print(e) ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值