jwt延期,刷新令牌还不够安全哦

关于token的安全认证, 如果其他用户拿到这个token, 岂不是可以访问该token对应的用户, 这就是为什么设置token设置超时的原因是吧? 那么如果我现在用的是jwt, 不可能用户活跃期间, 我还让用户重新登录吧, 那么我要如何重新对jwt进行延期呢? 有什么方案呢

注意: jwt中的header/playload 中只是经过base64加密的, 请不要把敏感数据放在playload负载中, 这跟在大街上拉粑粑有什么区别

jwt进行延期

Token泄露确实可能导致安全问题。设置Token超时(过期时间)是一种减小安全风险的方法,因为即使Token泄露,攻击者只能在有限的时间内利用它。然而,在用户活跃期间,我们通常不希望让他们重新登录。为此,您可以采取以下策略来延长JWT的有效期:

  1. 滑动会话(Sliding Session):每当用户与系统交互时,您可以生成一个新的JWT,并更新其过期时间。新的JWT可以在响应头或响应体中发送给客户端。客户端收到新的JWT后,将其替换为旧的JWT。这样,只要用户保持活跃,他们的会话将一直有效。需要注意的是,这种方法可能会增加服务器的负载,因为需要频繁生成新的JWT。

  2. 刷新令牌(Refresh Token):在用户登录时,除了返回一个访问令牌(Access Token)之外,还可以返回一个刷新令牌(Refresh Token)。访问令牌具有较短的过期时间,而刷新令牌具有较长的过期时间。当访问令牌过期时,客户端可以使用刷新令牌向认证服务器请求一个新的访问令牌。这样,在不需要用户重新登录的情况下,仅需在访问令牌过期时使用刷新令牌即可延长用户会话。请注意,刷新令牌本身也可能过期,此时用户需要重新登录。

以下是一个简单的使用刷新令牌的Java示例:

// 获取新的访问令牌和刷新令牌
public Map<String, String> getTokens(String userId) {
    String accessToken = generateJwt(userId, ACCESS_TOKEN_EXPIRATION);
    String refreshToken = generateJwt(userId, REFRESH_TOKEN_EXPIRATION);

    Map<String, String> tokens = new HashMap<>();
    tokens.put("access_token", accessToken);
    tokens.put("refresh_token", refreshToken);

    return tokens;
}

// 使用刷新令牌获取新的访问令牌
public String refreshAccessToken(String refreshToken) throws JWTVerificationException {
    // 验证刷新令牌
    DecodedJWT decodedRefreshToken = verifyJwt(refreshToken);
    String userId = decodedRefreshToken.getClaim("userId").asString();

    // 生成新的访问令牌
    return generateJwt(userId, ACCESS_TOKEN_EXPIRATION);
}

无论您选择哪种策略,都要确保在客户端和服务器端都有相应的安全措施。例如,使用HTTPS来防止Token在传输过程中被窃取,将Token存储在安全的地方(如浏览器的HttpOnly Cookie中),并定期检查和更新您的加密算法和密钥。

刷新令牌的示例

使用 刷新令牌(Refresh Token) 这种方案, 浏览器 A和前端 B, 后端C, 现在访问令牌已经过期, 但是刷新令牌还没过期, 浏览器 A和前端 B, 后端C分别做了什么, 才能刷新访问令牌, 说一下刷新访问令牌的过程

假设我们有浏览器A、前端应用B和后端服务C,这里是使用刷新令牌刷新访问令牌的过程:

  1. 浏览器A向前端应用B发送请求(例如,获取资源)。
  2. 前端应用B检查访问令牌是否过期。如果已过期,前端应用B将使用刷新令牌向后端服务C请求一个新的访问令牌。
  3. 后端服务C收到刷新令牌请求,验证刷新令牌的有效性。如果刷新令牌有效,后端服务C生成一个新的访问令牌,并将其发送给前端应用B。
  4. 前端应用B收到新的访问令牌,并将其存储起来(例如,在本地存储或内存中)。之后的请求将使用新的访问令牌。
  5. 前端应用B使用新的访问令牌重新发起之前失败的请求。
  6. 后端服务C验证新的访问令牌,并处理请求。

这里是一个简化的示例,展示了前后端如何进行访问令牌刷新:

前端(JavaScript):

// 发送请求
async function sendRequest() {
  // 获取访问令牌和刷新令牌
  const accessToken = localStorage.getItem("access_token");
  const refreshToken = localStorage.getItem("refresh_token");

  // 使用访问令牌发送请求
  const response = await fetch("https://api.example.com/resource", {
    headers: {
      "Authorization": `Bearer ${accessToken}`
    }
  });

  // 如果访问令牌过期,尝试刷新访问令牌
  if (response.status === 401) {
    const refreshedToken = await refreshAccessToken(refreshToken);
    if (refreshedToken) {
      // 保存新的访问令牌并重试请求
      localStorage.setItem("access_token", refreshedToken);
      return await sendRequest();
    } else {
      // 刷新令牌失败,提示用户重新登录
      alert("Session expired, please log in again.");
    }
  } else {
    return response;
  }
}

// 刷新访问令牌
async function refreshAccessToken(refreshToken) {
  const response = await fetch("https://api.example.com/refresh-token", {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify({ refresh_token: refreshToken })
  });

  if (response.ok) {
    const data = await response.json();
    return data.access_token;
  }

  return null;
}

后端(Java):


// 刷新访问令牌的API端点
@PostMapping("/refresh-token")
public ResponseEntity<Map<String, String>> refreshAccessToken(@RequestBody Map<String, String> payload) {
	String refreshToken = payload.get("refresh_token");

	try {
        // 使用刷新令牌获取新的访问令牌
		String newAccessToken = refreshAccessToken(refreshToken);

        // 返回新的访问令牌给前端
		Map<String, String> response = new HashMap<>();
		response.put("access_token", newAccessToken);
		return ResponseEntity.ok(response);
	} catch (JWTVerificationException e) {
    // 刷新令牌无效,返回401 Unauthorized
		return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
	}
}

// 使用刷新令牌获取新的访问令牌
public String refreshAccessToken(String refreshToken) throws JWTVerificationException {
// 验证刷新令牌
	DecodedJWT decodedRefreshToken = verifyJwt(refreshToken);
	String userId = decodedRefreshToken.getClaim("userId").asString();
// 生成新的访问令牌
	return generateJwt(userId, ACCESS_TOKEN_EXPIRATION);
}

// 其他相关方法(例如:generateJwt,verifyJwt 等)...

这个示例展示了前端如何在访问令牌过期后使用刷新令牌请求新的访问令牌,以及后端如何验证刷新令牌并生成新的访问令牌。实际实现可能会因项目需求和技术栈的不同而有所不同。在生产环境中,您还需要考虑其他安全措施,如使用HTTPS传输Token,将Token存储在安全的位置等。

如何提高 Token 使用过程中的整体安全性

在token的使用过程中, 可以使用HTTPS来防止Token在传输过程中被窃取,将Token存储在安全的地方(如浏览器的HttpOnly Cookie中),并定期检查和更新您的加密算法和密钥来加强安全措施, 那么HTTPS为什么可以防止Token在传输过程中被窃取, Token为什么要存放在HttpOnly Cookie中

  1. HTTPS 防止 Token 在传输过程中被窃取:HTTPS(超文本传输安全协议)是一种用于在网络上安全传输数据的协议。与 HTTP 不同,HTTPS 使用 SSL/TLS(安全套接层/传输层安全)对通信内容进行加密。这样,即使有人截获了通信数据,他们也无法轻易地解密出原始内容。因此,当使用 HTTPS 时,Token 在传输过程中被窃取的风险大大降低。

  2. Token 存放在 HttpOnly Cookie 中:将 Token 存储在 HttpOnly Cookie 中,是为了防止跨站脚本攻击(XSS)。跨站脚本攻击是一种攻击方式,攻击者利用漏洞将恶意脚本注入到网站页面,进而窃取用户的敏感信息。如果 Token 存储在普通的 Cookie 或 JavaScript 可访问的存储空间(如 LocalStorage)中,那么攻击者可能通过 XSS 攻击窃取 Token。而 HttpOnly Cookie 只能通过 HTTP 请求进行访问,不能通过 JavaScript 访问。这样,即使网站受到 XSS 攻击,攻击者也无法直接访问 HttpOnly Cookie 中的 Token,从而提高了安全性。

总结一下,使用 HTTPS 可以保护 Token 在网络传输过程中的安全性,而将 Token 存储在 HttpOnly Cookie 中则可以降低其在客户端被窃取的风险。这两个安全措施可以相互配合,提高 Token 使用过程中的整体安全性。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值