hi, i have a question
how can block in the behavior for give access to the action ONLY by ajax ?
any idea or i need create a custom filter for this case
for example
public function behaviors()
{
return [
'ajax' => [
'class' => AjaxFilter::className(),
'only' => ['action1','action2'],
]
];
}
and if you try enter with URL like (http://localhost/controller1/action1 you get 403
Check for Yii::$app->request->isAjax
@SDKiller i know but is better if we can assign this in the behavior no ?
yii2 no have filter access only ajax no ?
Something like this may work
class AjaxFilter extends \yii\base\ActionFilter
{
public function beforeAction($action)
{
if (Yii::$app->request->isAjax) {
return parent::beforeAction($action);
}
throw new BadRequestHttpException();
}
}
that will be work, i can suggest add a standard filter for yii2 respect this ?
well if any need this is my class
<?php
namespace common\components\filters;
use Yii;
use yii\base\ActionEvent;
use yii\base\ActionFilter;
use yii\web\Controller;
use yii\web\ForbiddenHttpException;
class AjaxAccess extends ActionFilter
{
public $defaultUrl = ['site/index'];
/**
* Declares event handlers for the [[owner]]'s events.
* @return array events (array keys) and the corresponding event handler methods (array values).
*/
public function events()
{
return [Controller::EVENT_BEFORE_ACTION => 'beforeAction'];
}
/**
* @param ActionEvent $event
* @return boolean
* @throws MethodNotAllowedHttpException when the request method is not allowed.
*/
public function beforeAction($event)
{
if (Yii::$app->request->isAjax)
return parent::beforeAction($event);
else
$this->denyAccess(Yii::$sapp->uer);
}
/**
* Denies the access of the user.
* The default implementation will redirect the user to the login page if he is a guest;
* if the user is already logged, a 403 HTTP exception will be thrown.
* @param Yii\web\User $user the current user
* @throws Yii\web\ForbiddenHttpException if the user is already logged in.
*/
protected function denyAccess($user)
{
if ($user->getIsGuest()) {
$user->loginRequired();
} else {
$this->ajaxOnly();
}
}
public function ajaxOnly()
{
if ($this->defaultUrl !== null) {
$defUrl = (array)$this->defaultUrl;
if ($defUrl[0] !== Yii::$app->requestedRoute)
return Yii::$app->getResponse()->redirect($this->defaultUrl);
}
throw new ForbiddenHttpException('Only ajax!');
}
}
and in the behavior add
'ajax' => [
'class' => AjaxAccess::className(),
'only' => ['list']
]
my suggestion is, add a AjaxFilter for define what actions only work in Ajax, can configure in main.php and create a standard for yii2 well is only a idea @qiangxue @samdark
thx for read this suggestion
AjaxFilter
would be useful, I think. Writing an if
operator each time the AJAX filtering is needed is a little bit verbose.
@maximal i know, :P i show a sample in this case
i propose to use the two already existing filters instead of creating a new one.
'access' => [
'class' => \yii\filters\AccessControl::className(),
'only' => ['create', 'update'],
'rules' => [
// allow only AJAX requests using the post Method
[
'allow' => true,
'ajax' => true,
'verbs' => ['POST']
],
],
]
AjaxFilter
would be really useful
+1
+1
beforeAction
can do the trick specially when you also need to do extra stuff with ajax requests like changing the response format:
private $_ajaxOnlyActions = ['create-api','create-resource'];
public function beforeAction($action) {
if (!parent::beforeAction($action)) return false;
foreach ($this->_ajaxOnlyActions as $action) {
if ($this->action->id === $action) {
if (Yii::$app->request->isAjax === false)
throw new \yii\web\BadRequestHttpException();
// all other ajax related stuff
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
}
}
return true;
}
limiting access to calls either ajax or non-ajax can be useful. Its so generic that usecases can be thought of. Imagining:
My solution, just check isAjax in matchCallback
.
public function behaviors()
{
return [
'access' => [
'class' => 'yii\filters\AccessControl',
'only' => ['buy-validate', 'buy'],
'rules' => [
// allow only AJAX requests using the post Method
[
'allow' => true,
'verbs' => ['POST'],
'matchCallback' => function () {
return Yii::$app->request->getIsAjax();
},
],
],
],
];
}
Because for use yii\filters\AccessControl
need user component and in some use case this component was may not be, you must write your filter like this => https://github.com/yiisoft/yii2/issues/4793#issuecomment-292174430
Most helpful comment
My solution, just check isAjax in
matchCallback
.