微信access_token和refresh_token保存于redis

时间:2021-12-31 05:12:39

简介

  • 通常理解的access_token和refresh_token
    • access_token是用来对客户端进行认证的,类似与密码,有一定的有效期。当过期后可使用refresh_token重新获取一个新的access_token。refresh_token的有效期相对较长
  • 微信开发设置到两种access_token
    • 第一种是接口授权access_token,是用来调用微信高级接口的,有次数限制,是来区分公众号的
    • 另外一种是用户授权access_token,是用户授权公众号获取用户信息是得到的,无次数限制,使用用来区分用户的(一般用在微信H5开发上)
  • 由于上述第一种access_token是有次数限制的,因此我们需要将太缓存(保存)起来,每次调用接口的时候先取我们缓存的access_token,而不是从新获取一个新的access_token。
  • 由于refresh_token的有效期相对较长,且使用频率较少,此处只说明access_token的保存(refresh_token可类似处理)

使用redis保存access_token

  • 微信公众平台API每日有调用上限,即使某些公众号或服务号有清零某些接口调用的次数权限,但也架不住滥用或错误的调用,官方建议access_token由一台服务来维护和提供查询功能,另外特别重要的一点是每个凭证都拥有生命周期,长短不同,access_token的生命周期是7200秒,在这段时间内可以重复使用,所以不要在每使用一次凭证就重新获取一个access_token了。
  • 通常会保存在内存数据库中,如Redis,当然也可以直接放在应用程序的内存中,不建议放在oracle或MySQL,拿取开销较比其它手段太重。放在内存数据库中的好处较比放在应用程序的内存中是维护性好,尤其是搭配了可视化管理工具后。另外不仅可以放access_token,也可以其它数据库。[^1] [^2]
  • 示例(基于springboot)

    • redis等其他基础配置省略

    • application.yml 其中myapp下的key都需要进行自定义参数配置,此处也存储了用户授权access_token

      myapp:
      redisWxUserAccessToken: "user.wxUserAccessToken"
      redisWxUserRefreshToken: "user.wxUserRefreshToken"
      redisWxAccessToken: "sys.wxAccessToken"
      redisWxRefreshToken: "sys.wxRefreshToken"
    • 此处以保存用户授权access_token为例,接口调用access_token可在项目启动时进行缓存。部分代码如下:

      @Autowired
      private RedisTemplate<String, String> redisTemplate; @Value("${myapp.redisWxUserAccessToken}")
      private String redisWxUserAccessToken; // 获取
      public String getUserAccessToken(Object userId) {
      String accessToken = null;
      if(StringUtils.isEmpty(userId)) return accessToken; String accessTokenStr = (String) redisTemplate.opsForHash().get(redisWxUserAccessToken, String.valueOf(userId));
      long now = (new Date()).getTime();
      if(!StringUtils.isEmpty(accessTokenStr)) {
      String[] arr = accessTokenStr.split("#"); if(now < Long.valueOf(arr[1])) {
      accessToken = arr[0];
      }
      } if(StringUtils.isEmpty(accessToken)) {
      accessToken = getUserAccessTokenByRefreshToken(userId);
      } return accessToken;
      } // 重新获取
      Object expiresIn = accessTokenMap.get("expires_in"); // 调用微信授权接口后,返回的expires_in参数
      String value = accessTokenNew + "#" + getNowExpiresIn(expiresIn); // 此处是设置有效期
      redisTemplate.opsForHash().put(redisWxUserAccessToken, String.valueOf(userId), value); public Long getNowExpiresIn(Object expiresIn) {
      long now = (new Date()).getTime();
      if(expiresIn == null) return now; Long expiresMs = Long.valueOf(String.valueOf(expiresIn)) - 15 * 60;
      return expiresMs * 1000 + now;
      }

[^1] 网页授权的access_token大家是怎么缓存的

[^2] https://segmentfault.com/q/1010000004995599/a-1020000005016398