I have a custom controller and I'm trying to define an action in the controller that could be accessed by the guest users. My controller code is the following:
class MyCustomController extends Controller
{
...
/**
* {@inheritdoc}
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
'access' => [
'class' => AccessControl::class,
'only' => ['live'],
'rules' => [
[
'allow' => true,
'actions' => ['live'],
'roles' => ['?'],
],
]
]
];
}
/**
* Live action.
* @return mixed
*/
public function actionLive()
{
return $this->render('live');
}
...
}
And the view code is this:
<?php
echo 'We are live!!';
?>
I also have this setting in frontend/config/main.php
return [
...
'as beforeRequest' => [
'class' => 'yii\filters\AccessControl',
'rules' => [
[
'actions' => ['login', 'error'],
'allow' => true,
],
[
'allow' => true,
'roles' => ['@'],
],
],
],
...
]
When I try to access the page http://my-webapp/my-custom/live
as an authenticated user I get the message Forbidden (#403)
which is ok (although displaying it for the authenticated users would be perfectly ok too).
But when I access that page as a guest user I get redirected to the login page. I just want to disable the redirect for this particular action and just let the guest users see that view.
CodePudding user response:
You are applying AccessControl
filter twice.
First filter is set for Application
so it is applied for each request with following rules:
- If the action id is "login" or "error" allow any user.
- Allow logged in users
- Deny any other request.
The second filter is for MyCustomController
and it's set to apply only for requests to action live
of that controller with following rules:
- Allow any user who is not logged in.
- Deny any other request.
So when request comes from user who is logged in, the request is stopped by second filter and the 403 error is displayed. When request comes from guest user it is stopped by first filter and user is redirected to login page.
To allow guests access your action you should add exception to first filter to make sure only second AccessControl
filter is applied:
return [
//...
'as beforeRequest' => [
'class' => 'yii\filters\AccessControl',
'except' => ['my-custom/live'],
'rules' => [
[
'actions' => ['login', 'error'],
'allow' => true,
],
[
'allow' => true,
'roles' => ['@'],
],
],
],
...
];
Actually, if you are OK with allowing any user to see the my-custom/live
there is no need for the second AccessControl
filter. Just setting the exception in the first (application wide) filter will be enough.