I have the following configuration in the web.php file to force users to login first before using the app.
'as access' => [
'class' => \yii\filters\AccessControl::className(), //AccessControl::className(),
'rules' => [
[
'actions' => ['login', 'error'],
'allow' => true,
],
[
'actions' => ['logout', 'index'], // add all actions to take guest to login page
'allow' => true,
'roles' => ['#'],
],
],
],
However I get a Forbidden (#403) error in the http://localhost/yii2/debug/default/toolbar?tag=58759099581f2
How to allow in that in the rules?
First of all, this config is incorrect. This part:
[
'actions' => ['logout', 'index'], // add all actions to take guest to login page
'allow' => true,
'roles' => ['#'],
],
will additionally allow only logout and index actions to authenticated users. It needs to be changed to:
[
'allow' => true,
'roles' => ['#'],
],
to allow access to the entire site. Then you can customize access further in AccessControl or actions of specific controllers. So debug is not the only forbidden page in your case.
I think it was copy pasted from this answer to related question here on SO.
And by the way debug is already enabled in application config in basic app:
if (YII_ENV_DEV) {
// configuration adjustments for 'dev' environment
$config['bootstrap'][] = 'debug';
$config['modules']['debug'] = [
'class' => 'yii\debug\Module',
// uncomment the following to add your IP if you are not connecting from localhost.
//'allowedIPs' => ['127.0.0.1', '::1'],
];
// Below Gii is enabled too, code is omitted for brevity
}
So when user is authenticated, you will have access to debug module without any problems.
Note: With this configuration login and error actions of every controller are allowed to non-authenticated users. Be careful with that. There is a chance of actions with similar names exist in other controllers.
Update: Actually you can go further and make this solution more flexible with $matchCallback:
'as access' => [
'class' => \yii\filters\AccessControl::className(),
'rules' => [
[
'matchCallback' => function ($rule, $action) {
$allowedControllers = [
'debug/default',
];
$allowedActions = [
'site/login',
'site/error',
];
$isAllowedController = in_array($action->controller->uniqueId, $allowedControllers);
$isAllowedAction = in_array($action->uniqueId, $allowedActions);
return $isAllowedController || $isAllowedAction;
},
'allow' => true,
],
[
'allow' => true,
'roles' => ['#'],
],
],
],
Place fully allowed controllers in $allowedControllers list (prefix it with module name if it's inside a module) to allow them completetely (allow all actions).
Place allowed actions in $allowedActions list (prefix it with controller name and with module name if it belongs to a module).
That way you can have full access to debug module on local server on every page (including login and error) which can be useful.
Also this prevents from action names coincidence from different modules / controllers.
You have to enable the toolbar action web.php config file:
'rules' => [
[
'actions' => ['login', 'error', 'toolbar'],
'allow' => true,
],
Related
I am using Yii2 (basic) and Yii2-user for a website with users. For most actions it's necessary to be authenticated. How could I make a controller / action accessible as a guest?
I have tried things like this in the guest's controller:
'rules' => [
[
'allow' => true,
'actions' => ['index', 'confirm', 'download-form', 'upload-form'],
]
],
And this should be enough. But nope. I suspect that it is Yii2-user module who gets in the way and always redirects me to login.
And I have added the module in the web.php configuration like this:
'components' => [
...
...
'user' => [
'class' => 'nkostadinov\user\components\User',
'identityClass' => 'nkostadinov\user\models\User',
'enableConfirmation' => false,
'as firstLoginPolicy' => [
'class' => 'nkostadinov\user\behaviors\FirstLoginPolicyBehavior'
],
],
],
Any idea?
I have solved it as follows.
In my web.php configuration I had this:
'modules' => [
...
],
'as access' => [
'class' => \yii\filters\AccessControl::className(),//AccessControl::className(),
'rules' => [
[
'actions' => ['login', 'error', 'request', 'change-password'],
'allow' => true,
'roles' => ['?']
],
[
//'actions' => ['logout', 'index'], // add all actions to take guest to login page
'allow' => true,
'roles' => ['#'],
],
],
],
'params' => [ ... ]
So, I have added this new rule to grant guest users access to all actions of this controller:
[
'controllers' => ['mymodule/my-controller'],
'allow' => true,
],
And that's it.
i suggest you to use mdmsoft/yii2-admin for authentication
I am starting up with yii2
I dont have any idea of previous version of YII
But I have good knowledge of codeigniter and have been working in codeigniter from last 3 years.
MY Question is as below :
There is a function name behaviors() in SiteController.php file.
It has below code. I want to know what does it do?
public function behaviors() {
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['logout'],
'rules' => [
[
'actions' => ['logout'],
'allow' => true,
'roles' => ['#'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
];
}
In the sample you privided there are two part
'access'
and
'verbs'
the access section configure the Access Control Filter rules
http://www.yiiframework.com/doc-2.0/yii-filters-accesscontrol.html
one of the authorization method implemented by Yii2 ( best used by applications that only need some simple access control)
and http://www.yiiframework.com/doc-2.0/yii-filters-verbfilter.html
that define the allowed HTTP request methods for each action. VerbFilter checks if the HTTP request methods are allowed by the requested actions. If not allowed, it will throw an HTTP 405 exception.
In your case set that the action logout must performed by a post method
for a brief guide you can see
http://www.yiiframework.com/doc-2.0/guide-structure-filters.html
I want to call some actions only when user is logged in.
How to do it without checking the user login status every time?
You will need to add a behaviors() method to your controller such as :
public function behaviors()
{
return [
'access' => [
'class' => \yii\filters\AccessControl::className(),
'only' => ['login', 'logout', 'signup'],
'rules' => [
[
'allow' => true,
'actions' => ['login', 'signup'],
'roles' => ['?'],
],
[
'allow' => true,
'actions' => ['logout'],
'roles' => ['#'],
],
],
],
];
}
The roles defined above are # for all users that are logged in and ? for all users that aren't logged in. In your case you will be interrested in setting the role to #.
You can of course replace these with any rbac roles/permissions.
Here's more information on authorization from the Yii2 guide
When i use such access rules
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'allow' => true,
'roles' => ['?'],
],
],
'rules' => [
[
'allow' => true,
'roles' => ['#'],
],
],
'denyCallback' => function ($rule, $action) {
echo 'Denied';
}
],
];
}
The result is: logged-in users can see the page, but unlogged-in users can't see the page (it strange because the rule for unlogged-in user is the first and here http://www.yiiframework.com/doc-2.0/guide-security-authorization.html we can read
ACF performs the authorization check by examining the access rules one
by one from top to bottom until it finds a rule that matches the
current execution context.
So, why the first rule for unlogged-in users don't work, but the second rule for logged-in user works?
This is because you wrote rules two times. As a result you get associative array with two identical keys. PHP allows add elements with the same keys into associative array but it leads to weird behavior. As far as I remember the latest declared element will have priority.
So your rules are actually are:
'rules' => [
[
'allow' => true,
'roles' => ['#'],
],
],
That's why only logged-in users are allowed, everything is correct.
Should be changed to:
'rules' => [
[
'allow' => true,
'roles' => ['?'],
],
[
'allow' => true,
'roles' => ['#'],
],
],
But think logically about what you want - it doesn't make sense. Logged-in users can access all actions and guests can access all actions. So all users can access all actions within this controller. As a conclusion - for the current state you don't need declare any access rules and can just omit that.
In Yii2 advanced template, they have the signup components for new users in the frontend.
I want to put that signup process into the /backend so that only admin users can create other new users.
So in moving SignupForm, signup view, adding the Signup action to the backend/SiteController, I'm getting 403 error "You are not allowed to perform this action".
Has anyone been able to put the signup process into the backend of the advanced template in Yii2 ?
What I want to do is have admin users create the new user and give the login details to the external party. The external party would then be advised to run the Password Reset, in order to set their own password. But effectively, its locking down the registration/signup process.
Its nothing that should stop you from making this work. But will need to change a few things along the way.
First off, I guess your error message comes from the AccessControl that the backend SiteController has:
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['login', 'error'],
'allow' => true,
],
[
'actions' => ['logout', 'index'],
'allow' => true,
'roles' => ['#'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
];
}
Change this to:
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['login', 'error'],
'allow' => true,
],
[
'actions' => ['logout', 'index', 'signup'],
'allow' => true,
'roles' => ['#'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
];
}
Orelse this will result in the error message:
Forbidden (#403)
You are not allowed to perform this action.
Remember that the signup function is made for guests registering, and that it automatically out-of-the box log the user in when the account is created.
You have to remove this feature, and you might encounter some other bugs along the way.
Good Luck.