微信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

相關文章
相關標籤/搜索