微信access_token和refresh_token保存于redis

简介

  • 一般理解的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)php

    • redis等其余基础配置省略
    • application.yml 其中myapp下的key都须要进行自定义参数配置,此处也存储了用户受权access_tokenjava

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

      @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-1020000005016398spring