防止access_token失效 法一(存redis里)

本文介绍了一个用于微信JS-SDK配置的PHP类,包括获取access_token、jsapi_ticket及生成signature的过程。通过连接Redis存储access_token和jsapi_ticket,减少API调用频率,提高效率。
<?php
namespace Index\Model;
use Think\Model;
class WeixinshareModel extends Model
{
    protected $trueTableName='kqy_video';
    const APPID = '***';
    const APPSECRET = '***';
    public $redis;
    function __construct()
    {
          $this->redis=new \redis();
          $this->redis->connect('127.0.0.1', 6379);
          $this->redis->auth('****');
         parent::__construct();
    }
    //获取access_token
    public function accessToken()
    {
          
         $access_token =$this->redis->get("weixin_access_token");//存入redis,这里要结合自己的项目,对redis或者memcahe进行设置
        if(!$access_token){
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".self::APPID."&secret=".self::APPSECRET;
            $data = json_decode($this->httpGet($url),true);
            if(isset($data['access_token']) && $data['access_token'] != ''){
                $this->redis->set("weixin_access_token",$data['access_token'],7200);
                $access_token=$data['access_token'];
            }else{
                return false;
            }
        }
        
        return $access_token;
    }
    //用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket
    public function jsapiTicket()
    {
         $jsapi_ticket =$this->redis->get("weixin_jsapi_ticket");
        if(!$jsapi_ticket){
            $access_token = $this->accessToken();
            if($access_token){
                $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=".$access_token."&type=jsapi";
                $data = json_decode($this->httpGet($url),true);
                if(isset($data['errcode']) && $data['errcode']== 0){//请求成功
                   $this->redis->set("weixin_jsapi_ticket",$data['ticket'],7200);
                   $jsapi_ticket=$data['ticket'];
                }else{
                    return false;
                }
            }else{
                return false;
            }
        }
       
        return $jsapi_ticket;
    }
    //获取signature
    public function signature($nonceStr,$timestamp,$url)
    {
        $jsapi_ticket = $this->jsapiTicket();
        $signature = '';
        if($jsapi_ticket) {
            $string = "jsapi_ticket=$jsapi_ticket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";
            $signature = sha1($string);//对string1进行sha1签名,得到signature
        }else{
            return false;
        }
       
        return $signature;
    }
    public function createNonceStr() {
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $str = "";
        for ($i = 0; $i < 16; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }
    public function httpGet($url)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_TIMEOUT, 500);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($curl, CURLOPT_URL, $url);
        $res = curl_exec($curl);
        curl_close($curl);
        return $res;
    }

}
在Java中,应用系统可以按照以下步骤实现通过code获取access_token并管理其有效期: 1. **调用接口获取access_token**: 使用HTTP客户端库(如Apache HttpClient、OkHttp或Spring的RestTemplate),构造个请求发送到统门户提供的API端点。这个端点通常接受授权码(code)作为参数,并返回新的access_token。 ```java import org.apache.http.client.HttpClient; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; String apiUrl = "统门户接口地址"; HttpPost httpPost = new HttpPost(apiUrl); httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded"); StringEntity params = new StringEntity("grant_type=authorization_code&code=your_code"); httpPost.setEntity(params); HttpClient httpClient = HttpClientBuilder.create().build(); CloseableHttpResponse response = null; try { response = httpClient.execute(httpPost); // ...处理响应,获取access_token } finally { if (response != null) { response.close(); } } ``` 2. **保access_token**: 将获取到的access_token储在个安全的地方,如数据库、内(例如Redis)或者JWT(JSON Web Token)中,设置合理的过期时间。 ```java import com.fasterxml.jackson.databind.ObjectMapper; import net.minidev.json.JSONObject; // JSON库 // 假设我们使用HashMap储 Map<String, String> tokenCache = new HashMap<>(); JSONObject accessTokenObj = new JSONObject(); accessTokenObj.put("token", accessToken); accessTokenObj.put("expires_at", String.valueOf(System.currentTimeMillis() + (2 * 60 * 60 * 1000))); // 过期时间(2小时) tokenCache.put(appId, accessTokenObj.toString()); ``` 3. **检查并刷新access_token**: 当需要访问受保护的资源之前,先检查access_token是否已过期。如果未过期,则直接使用;如果已过期,调用刷新接口(通常需要使用refresh_token)获取新token,然后更新缓。 ```java public synchronized String getTokenForApp(String appId) { String accessTokenFromCache = tokenCache.get(appId); if (accessTokenFromCache == null || isAccessTokenExpired(accessTokenFromCache)) { // 刷新access_token String refreshToken = getRefreshToken(appId); // 获取refresh_token accessToken = refreshTokenAccessToken(refreshToken); updateTokenCache(appId, accessToken); } return accessToken; } private boolean isAccessTokenExpired(String accessTokenJson) { try { JSONObject accessTokenObject = new JSONObject(accessTokenJson); long expiresIn = Long.parseLong(accessTokenObject.get("expires_in").toString()); long currentTime = System.currentTimeMillis(); return currentTime > Long.parseLong(accessTokenObject.get("expires_at").toString()) - expiresIn * 1000; } catch (Exception e) { return true; // 认定已过期 } } private String refreshTokenAccessToken(String refreshToken) { // 调用刷新接口并替换access_token // ... return newAccessToken; } private void updateTokenCache(String appId, String accessToken) { tokenCache.put(appId, accessToken); } ``` 4. **注销功能**: 实现个方用于主动清除access_token,这通常涉及到向服务端发送个注销请求,服务端在接收到请求后会从其记录中删除该用户的access_token。 ```java public void logoutUser(String appId) { String refreshToken = getTokenForApp(appId).get("refresh_token"); // 发送注销请求 revokeTokenApi(refreshToken); // 清除本地缓 tokenCache.remove(appId); } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值