yii2-ratelimiter-advanced
yii2-ratelimiter-advanced copied to clipboard
"Trying to get property 'id' of non-object" error
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',
]
];