yii2-ratelimiter-advanced icon indicating copy to clipboard operation
yii2-ratelimiter-advanced copied to clipboard

"Trying to get property 'id' of non-object" error

Open tsvetiligo opened this issue 4 years ago • 6 comments

I try to use "Basic Limit Per User ID" code from recipes and get "Trying to get property 'id' of non-object" error. I use HttpBearerAuth and user don't login yet then this code runs.

I want to use limit per user if user is logged in, and if not - limit per IP. How can I achieve this behavior?

behaviors() code in my controller:

public function behaviors()
    {
        $behaviors = parent::behaviors();

        unset($behaviors['rateLimiter']);

        $behaviors['authenticator'] = [
            'class' => \yii\filters\auth\CompositeAuth::className(),
            'authMethods' => [
                \yii\filters\auth\HttpBearerAuth::className(),
            ],
        ];

        $behaviors['verbs'] = [
            'class' => \yii\filters\VerbFilter::className(),
            'actions' => $this->actions,
        ];

        // remove authentication filter
        $auth = $behaviors['authenticator'];
        unset($behaviors['authenticator']);

        // add CORS filter
        $behaviors['corsFilter'] = [
            'class' => \yii\filters\Cors::className(),
            'cors' => [
                'Origin' => ['*'],
                'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
                'Access-Control-Request-Headers' => ['*'],
            ],
        ];

        // re-add authentication filter
        $behaviors['authenticator'] = $auth;
        // avoid authentication on CORS-pre-flight requests (HTTP OPTIONS method)
        $behaviors['authenticator']['except'] = array_merge($this->getExcept(), ['options']);
        $behaviors['authenticator']['optional'] = $this->getOptional();

        $behaviors['access'] = [
            'class' => \yii\filters\AccessControl::className(),
            'rules' => $this->rules,
        ];

        $behaviors['rateLimiter'] = [
            'class' => 'thamtech\ratelimiter\RateLimiter',
            'components' => [
                'rateLimit' => [
                    'definitions' => [
                        'basic' => [
                            // at most 100 requests within 600 seconds
                            'limit' => 100,
                            'window' => 600,
                            // this causes a separate rate limit to be tracked for
                            // each user ID
                            'identifier' => Yii::$app->user->getIdentity()->id,
                        ],
                    ],
                ],
                'allowanceStorage' => [
                    'cache' => 'cache', // use Yii::$app->cache component
                ],
                // add X-Rate-Limit-* HTTP headers to the response
                'as rateLimitHeaders' => 'thamtech\ratelimiter\handlers\RateLimitHeadersHandler',
                // throw TooManyRequestsHttpException when the limit is exceeded
                'as tooManyRequestsException' => 'thamtech\ratelimiter\handlers\TooManyRequestsHttpExceptionHandler',
            ]
        ];

        return $behaviors;
    }

Also I try to implement RateLimitInterface in my User model, but it don't work at all.

in User model:

public function getRateLimit($context)
    {
        $RateLimit = new RateLimit();
        $RateLimit->limit = 1;
        $RateLimit->window = 60;
        $RateLimit->identifier = $this->getId();

        return $RateLimit;
    }

in controller:

$behaviors['rateLimiter'] = [
            'class' => 'thamtech\ratelimiter\RateLimiter',
            'components' => [
                'rateLimit' => [
                    'definitions' => [
                        'user' => [
                            'class' => 'app\models\User', // implements RateLimitInterface
                        ],
                    ],
                ],
                'allowanceStorage' => [
                    'cache' => 'cache', // use Yii::$app->cache component
                ],
                // add X-Rate-Limit-* HTTP headers to the response
                'as rateLimitHeaders' => 'thamtech\ratelimiter\handlers\RateLimitHeadersHandler',
                // throw TooManyRequestsHttpException when the limit is exceeded
                'as tooManyRequestsException' => 'thamtech\ratelimiter\handlers\TooManyRequestsHttpExceptionHandler',
            ]
        ];

tsvetiligo avatar May 17 '20 18:05 tsvetiligo