overtrue / laravel-wechat

微信 SDK for Laravel, 基于 overtrue/wechat
MIT License
2.87k stars 501 forks source link

使用你的中间件oauth,你在获取user()的时候获取AccessToken没有做缓存 #119

Closed jiangxianli closed 6 years ago

jiangxianli commented 7 years ago

使用你的中间件oauth,你在获取user()的时候获取AccessToken没有做缓存,导致每个用户登录一次就去请求一次微信服务器,请求接口频率超限制了。

        if (!session('wechat.oauth_user') || $this->needReauth($scopes)) {
            if ($request->has('code')) {
                session(['wechat.oauth_user' => $this->wechat->oauth->user()]);
                $isNewSession = true;

                Event::fire(new WeChatUserAuthorized(session('wechat.oauth_user'), $isNewSession));

                return redirect()->to($this->getTargetUrl($request));
            }

            session()->forget('wechat.oauth_user');

            return $this->wechat->oauth->scopes($scopes)->redirect($request->fullUrl());
        }
 /**
     * {@inheritdoc}
     */
    public function user(AccessTokenInterface $token = null)
    {
        if (is_null($token) && $this->hasInvalidState()) {
            throw new InvalidStateException();
        }

        $token = $token ?: $this->getAccessToken($this->getCode());

        $user = $this->getUserByToken($token);

        $user = $this->mapUserToObject($user)->merge(['original' => $user]);

        return $user->setToken($token)->setProviderName($this->getName());
    }
/**
     * Get the access token for the given code.
     *
     * @param string $code
     *
     * @return \Overtrue\Socialite\AccessTokenInterface
     */
    public function getAccessToken($code)
    {
        if ($this->accessToken) {
            return $this->accessToken;
        }

        $postKey = (version_compare(ClientInterface::VERSION, '6') === 1) ? 'form_params' : 'body';

        $response = $this->getHttpClient()->post($this->getTokenUrl(), [
            'headers' => ['Accept' => 'application/json'],
            $postKey => $this->getTokenFields($code),
        ]);

        return $this->parseAccessToken($response->getBody());
    }
mingyoung commented 7 years ago
wx20170816-141405 2x
overtrue commented 7 years ago

@mingyoung 哈哈,而且加上 session 逻辑以后,你网站每天有 5000000 用户需要登录么?

jiangxianli commented 7 years ago

@mingyoung @overtrue 谢谢解答,确实不是这里的问题! 我的这个超限制是因为

    public function getCache()
    {
        return $this->cache ?: $this->cache = new FilesystemCache(sys_get_temp_dir());
    }

位于:vendor\overtrue\wechat\src\Core\AccessToken.php Line 184 这里用到sys_get_temp_dir() 做缓存目录,我这的网站用户是nginx , 默认这个目录是root权限 因为没有权限的原因,导致access_token没有缓存进去,所以每一次请求都去新生成了一个AccessToken 也没有报错提示,所以一直在刷新AccessToken。

 $app = new Application(['app_id' => env('WECHAT_APPID'), 'secret' => env('WECHAT_SECRET')]);
        $js = $app->js;

        return $js->config(array(
            'chooseImage',
            'uploadImage',
            'previewImage',
            'onMenuShareQQ',
            'onMenuShareWeibo',
            'onMenuShareTimeline',
            'onMenuShareAppMessage'
        ), false);
jiangxianli commented 7 years ago

@overtrue 希望优化下,检查一下缓存目录的读写权限,没有权限给个异常提示。

overtrue commented 7 years ago

你是不是关了报错啊?也许有警告呢?

anyforever commented 6 years ago

@jiangxianli 这个你用内存缓存,也能化解这个权限问题了 @overtrue 我想问一下,token线上缓存了,线下开发的,本地没有这个数据,也会去微信取,那样就把线上的给冲掉作废了,这个是怎么解决的? 微信是建议开发人员自己做中控服务器缓存这个数据,自己的开发用数据的时候都从自己中控缓存的那取

overtrue commented 6 years ago

@jiangxianli token 的缓存目录你是可以自定义的,这里使用了第三方缓存组件,所以能不能写进去我也不晓得,而且你这个目录不可写的话,你的其它功能应该也会受影响,比如文件上传,所以在部署 web 服务器的时候这些权限问题处理好,或者你在配置里指定其它缓存目录或者驱动都可以。

@anyforever 关于 “token线上缓存了,线下开发的” 本身这个 SDK 就是支持自定义 token 的,请参考自定义 access_token

anyforever commented 6 years ago

@overtrue 嗯。谢谢。写了个中间件干这事。