页面没有正确重定向错误,插件 CakeDC/Users 创建新用户没有超级用户
The page isn’t redirecting properly error with plugin CakeDC/Users creating new user no superuser
我进行了全新安装。 CakePHP 3.6 和 CakeDC/Users 一切都遵循文档。
我已经在 admin 前缀下创建了具有用户管理特征的自定义 UsersController.php,并且在使用超级用户(从命令行创建)登录后,我设法创建了具有 "admin" 角色的新用户。然后注销并使用新用户登录,浏览器显示 "The page isn’t redirecting properly" 错误。
社交登录已禁用。
/src/Config/bootstrap.php
...
Configure::write('Users.roles', ['superuser', 'admin', 'user']);
Configure::write('Users.config', ['users']);
Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]);
...
/src/Config/users.php
<?php
/**
* Copyright 2010 - 2017, Cake Development Corporation (https://www.cakedc.com)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2010 - 2017, Cake Development Corporation (https://www.cakedc.com)
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
use Cake\Core\Configure;
use Cake\Routing\Router;
$config = [
'Users' => [
// Table used to manage users
'table' => 'CakeDC/Users.Users',
// Controller used to manage users plugin features & actions
'controller' => 'CakeDC/Users.Users',
// configure Auth component
'auth' => true,
// Password Hasher
'passwordHasher' => '\Cake\Auth\DefaultPasswordHasher',
// token expiration, 1 hour
'Token' => ['expiration' => 3600],
'Email' => [
// determines if the user should include email
'required' => true,
// determines if registration workflow includes email validation
'validate' => true,
],
'Registration' => [
// determines if the register is enabled
'active' => false,
// determines if the reCaptcha is enabled for registration
'reCaptcha' => true,
// allow a logged in user to access the registration form
'allowLoggedIn' => false,
//ensure user is active (confirmed email) to reset his password
'ensureActive' => false,
// default role name used in registration
'defaultRole' => 'user',
],
'reCaptcha' => [
// reCaptcha key goes here
'key' => null,
// reCaptcha secret
'secret' => null,
// use reCaptcha in registration
'registration' => false,
// use reCaptcha in login, valid values are false, true
'login' => false,
],
'Tos' => [
// determines if the user should include tos accepted
'required' => true,
],
'Social' => [
// enable social login
'login' => false,
// enable social login
'authenticator' => 'CakeDC/Users.Social',
],
'GoogleAuthenticator' => [
// enable Google Authenticator
'login' => false,
'issuer' => null,
// The number of digits the resulting codes will be
'digits' => 6,
// The number of seconds a code will be valid
'period' => 30,
// The algorithm used
'algorithm' => 'sha1',
// QR-code provider (more on this later)
'qrcodeprovider' => null,
// Random Number Generator provider (more on this later)
'rngprovider' => null
],
'Profile' => [
// Allow view other users profiles
'viewOthers' => false,
'route' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile'],
],
'Key' => [
'Session' => [
// session key to store the social auth data
'social' => 'Users.social',
// userId key used in reset password workflow
'resetPasswordUserId' => 'Users.resetPasswordUserId',
],
// form key to store the social auth data
'Form' => [
'social' => 'social'
],
'Data' => [
// data key to store the users email
'email' => 'email',
// data key to store email coming from social networks
'socialEmail' => 'info.email',
// data key to check if the remember me option is enabled
'rememberMe' => 'remember_me',
],
],
// Avatar placeholder
'Avatar' => ['placeholder' => 'CakeDC/Users.avatar_placeholder.png'],
'RememberMe' => [
// configure Remember Me component
'active' => false,
'checked' => true,
'Cookie' => [
'name' => 'remember_me',
'Config' => [
'expires' => '1 month',
'httpOnly' => true,
]
]
],
],
'GoogleAuthenticator' => [
'verifyAction' => [
'plugin' => 'CakeDC/Users',
'controller' => 'Users',
'action' => 'verify',
'prefix' => false,
],
],
// default configuration used to auto-load the Auth Component, override to change the way Auth works
'Auth' => [
'loginAction' => [
'plugin' => 'CakeDC/Users',
'controller' => 'Users',
'action' => 'login',
'prefix' => false
],
'loginRedirect' => [
'prefix' => 'admin',
'plugin' => 'Articles',
'controller' => 'Articles',
'action' => 'index'
],
'authenticate' => [
'all' => [
'finder' => 'auth',
],
'CakeDC/Auth.ApiKey',
'CakeDC/Auth.RememberMe',
'Form' => [
'fields' => [
'username' => 'email'
]
],
],
'authorize' => [
'CakeDC/Auth.Superuser',
'CakeDC/Auth.SimpleRbac',
],
],
'OAuth' => [
'path' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', 'prefix' => null],
'providers' => [
'facebook' => [
'className' => 'League\OAuth2\Client\Provider\Facebook',
'options' => [
'graphApiVersion' => 'v2.8', //bio field was deprecated on >= v2.8
'redirectUri' => Router::fullBaseUrl() . '/auth/facebook',
'linkSocialUri' => Router::fullBaseUrl() . '/link-social/facebook',
'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/facebook',
]
],
'twitter' => [
'options' => [
'redirectUri' => Router::fullBaseUrl() . '/auth/twitter',
'linkSocialUri' => Router::fullBaseUrl() . '/link-social/twitter',
'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/twitter',
]
],
'linkedIn' => [
'className' => 'League\OAuth2\Client\Provider\LinkedIn',
'options' => [
'redirectUri' => Router::fullBaseUrl() . '/auth/linkedIn',
'linkSocialUri' => Router::fullBaseUrl() . '/link-social/linkedIn',
'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/linkedIn',
]
],
'instagram' => [
'className' => 'League\OAuth2\Client\Provider\Instagram',
'options' => [
'redirectUri' => Router::fullBaseUrl() . '/auth/instagram',
'linkSocialUri' => Router::fullBaseUrl() . '/link-social/instagram',
'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/instagram',
]
],
'google' => [
'className' => 'League\OAuth2\Client\Provider\Google',
'options' => [
'userFields' => ['url', 'aboutMe'],
'redirectUri' => Router::fullBaseUrl() . '/auth/google',
'linkSocialUri' => Router::fullBaseUrl() . '/link-social/google',
'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/google',
]
],
'amazon' => [
'className' => 'Luchianenco\OAuth2\Client\Provider\Amazon',
'options' => [
'redirectUri' => Router::fullBaseUrl() . '/auth/amazon',
'linkSocialUri' => Router::fullBaseUrl() . '/link-social/amazon',
'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/amazon',
]
],
],
]
];
return $config;
/src/Config/permissions.php
<?php
return [
'Users.SimpleRbac.permissions' => [
//admin role allowed to all the things
[
'role' => [GROUP_SUPER_ID, GROUP_ADMIN_ID],
'prefix' => '*',
'extension' => '*',
'plugin' => '*',
'controller' => '*',
'action' => '*'
],
//specific actions allowed for the all roles in Users plugin
[
'role' => '*',
'plugin' => 'CakeDC/Users',
'controller' => 'Users',
'action' => ['profile', 'logout', 'linkSocial', 'callbackLinkSocial'],
],
[
'role' => '*',
'plugin' => 'CakeDC/Users',
'controller' => 'Users',
'action' => 'resetGoogleAuthenticator',
'allowed' => function (array $user, $role, \Cake\Http\ServerRequest $request) {
$userId = \Cake\Utility\Hash::get($request->getAttribute('params'), 'pass.0');
if (!empty($userId) && !empty($user)) {
return $userId === $user['id'];
}
return false;
}
],
//all roles allowed to Pages/display
[
'role' => '*',
//'plugin' => null,
'controller' => 'Pages',
'action' => 'display',
]
]
];
/src/Controllers/Admin/UsersController.php
<?php
namespace App\Controller\Admin;
use App\Controller\Admin\AppController;
use CakeDC\Users\Controller\Traits\ProfileTrait;
use CakeDC\Users\Controller\Traits\SimpleCrudTrait;
use CakeDC\Users\Model\Table\UsersTable;
use Cake\Utility\Inflector;
/**
* Users Controller
*
*
* @method \App\Model\Entity\User[]|\Cake\Datasource\ResultSetInterface paginate($object = null, array $settings = [])
*/
class UsersController extends AppController
{
use ProfileTrait;
use SimpleCrudTrait {
index as protected traitIndex;
add as protected traitAdd;
edit as protected traitEdit;
}
public function index()
{
$table = $this->loadModel();
$authUser = $this->Auth->user();
$conditions = [];
if ($authUser['role'] != GROUP_SUPER_ID) {
$conditions['role !='] = GROUP_SUPER_ID;
}
$tableAlias = $table->alias();
$this->set($tableAlias, $this->paginate($table, $conditions));
$this->set('tableAlias', $tableAlias);
$this->set('_serialize', [$tableAlias, 'tableAlias']);
}
/**
* Add method
*
* @return mixed Redirects on successful add, renders view otherwise.
*/
public function add()
{
$table = $this->loadModel();
$tableAlias = $table->alias();
$entity = $table->newEntity();
$this->set($tableAlias, $entity);
$this->set('tableAlias', $tableAlias);
$this->set('_serialize', [$tableAlias, 'tableAlias']);
if (!$this->request->is('post')) {
return;
}
$entity = $table->patchEntity($entity, $this->request->getData());
$entity->role = $this->request->data('role');
$singular = Inflector::singularize(Inflector::humanize($tableAlias));
if ($table->save($entity)) {
$this->Flash->success(__d('CakeDC/Users', 'The {0} has been saved', $singular));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__d('CakeDC/Users', 'The {0} could not be saved', $singular));
}
/**
* Edit method
*
* @param string|null $id User id.
* @return mixed Redirects on successful edit, renders view otherwise.
* @throws NotFoundException When record not found.
*/
public function edit($id = null)
{
$table = $this->loadModel();
$tableAlias = $table->alias();
$entity = $table->get($id, [
'contain' => []
]);
$this->set($tableAlias, $entity);
$this->set('tableAlias', $tableAlias);
$this->set('_serialize', [$tableAlias, 'tableAlias']);
if (!$this->request->is(['patch', 'post', 'put'])) {
return;
}
$entity = $table->patchEntity($entity, $this->request->getData());
$entity->role = $this->request->data('role');
$singular = Inflector::singularize(Inflector::humanize($tableAlias));
if ($table->save($entity)) {
$this->Flash->success(__d('CakeDC/Users', 'The {0} has been saved', $singular));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__d('CakeDC/Users', 'The {0} could not be saved', $singular));
}
}
如果我直接更改数据库并将字段 "is_superuser" 设置为“1”,则新用户可以正确登录。但是我找不到问题出在哪里。
谢谢。
当调试为真时检查 debug.log 以了解规则评估和调试问题。看起来登录用户(调试来自 $this->Auth->user()
角色的用户数据与您定义的规则不匹配。
还要检查定义权限的正确密钥是 CakeDC/Auth.permissions
请参阅 https://github.com/CakeDC/users/blob/master/config/permissions.php#L53
我会修改规则
[
'role' => [GROUP_SUPER_ID, GROUP_ADMIN_ID],
'prefix' => '*',
'extension' => '*',
'plugin' => '*',
'controller' => '*',
'action' => '*'
],
并将角色更改为*
然后调试用户并匹配角色是正确的。首先检查您是否可以通过此规则访问目标页面,然后开始将规则限制为您需要的内容。
我进行了全新安装。 CakePHP 3.6 和 CakeDC/Users 一切都遵循文档。 我已经在 admin 前缀下创建了具有用户管理特征的自定义 UsersController.php,并且在使用超级用户(从命令行创建)登录后,我设法创建了具有 "admin" 角色的新用户。然后注销并使用新用户登录,浏览器显示 "The page isn’t redirecting properly" 错误。 社交登录已禁用。
/src/Config/bootstrap.php
...
Configure::write('Users.roles', ['superuser', 'admin', 'user']);
Configure::write('Users.config', ['users']);
Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]);
...
/src/Config/users.php
<?php
/**
* Copyright 2010 - 2017, Cake Development Corporation (https://www.cakedc.com)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2010 - 2017, Cake Development Corporation (https://www.cakedc.com)
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
use Cake\Core\Configure;
use Cake\Routing\Router;
$config = [
'Users' => [
// Table used to manage users
'table' => 'CakeDC/Users.Users',
// Controller used to manage users plugin features & actions
'controller' => 'CakeDC/Users.Users',
// configure Auth component
'auth' => true,
// Password Hasher
'passwordHasher' => '\Cake\Auth\DefaultPasswordHasher',
// token expiration, 1 hour
'Token' => ['expiration' => 3600],
'Email' => [
// determines if the user should include email
'required' => true,
// determines if registration workflow includes email validation
'validate' => true,
],
'Registration' => [
// determines if the register is enabled
'active' => false,
// determines if the reCaptcha is enabled for registration
'reCaptcha' => true,
// allow a logged in user to access the registration form
'allowLoggedIn' => false,
//ensure user is active (confirmed email) to reset his password
'ensureActive' => false,
// default role name used in registration
'defaultRole' => 'user',
],
'reCaptcha' => [
// reCaptcha key goes here
'key' => null,
// reCaptcha secret
'secret' => null,
// use reCaptcha in registration
'registration' => false,
// use reCaptcha in login, valid values are false, true
'login' => false,
],
'Tos' => [
// determines if the user should include tos accepted
'required' => true,
],
'Social' => [
// enable social login
'login' => false,
// enable social login
'authenticator' => 'CakeDC/Users.Social',
],
'GoogleAuthenticator' => [
// enable Google Authenticator
'login' => false,
'issuer' => null,
// The number of digits the resulting codes will be
'digits' => 6,
// The number of seconds a code will be valid
'period' => 30,
// The algorithm used
'algorithm' => 'sha1',
// QR-code provider (more on this later)
'qrcodeprovider' => null,
// Random Number Generator provider (more on this later)
'rngprovider' => null
],
'Profile' => [
// Allow view other users profiles
'viewOthers' => false,
'route' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile'],
],
'Key' => [
'Session' => [
// session key to store the social auth data
'social' => 'Users.social',
// userId key used in reset password workflow
'resetPasswordUserId' => 'Users.resetPasswordUserId',
],
// form key to store the social auth data
'Form' => [
'social' => 'social'
],
'Data' => [
// data key to store the users email
'email' => 'email',
// data key to store email coming from social networks
'socialEmail' => 'info.email',
// data key to check if the remember me option is enabled
'rememberMe' => 'remember_me',
],
],
// Avatar placeholder
'Avatar' => ['placeholder' => 'CakeDC/Users.avatar_placeholder.png'],
'RememberMe' => [
// configure Remember Me component
'active' => false,
'checked' => true,
'Cookie' => [
'name' => 'remember_me',
'Config' => [
'expires' => '1 month',
'httpOnly' => true,
]
]
],
],
'GoogleAuthenticator' => [
'verifyAction' => [
'plugin' => 'CakeDC/Users',
'controller' => 'Users',
'action' => 'verify',
'prefix' => false,
],
],
// default configuration used to auto-load the Auth Component, override to change the way Auth works
'Auth' => [
'loginAction' => [
'plugin' => 'CakeDC/Users',
'controller' => 'Users',
'action' => 'login',
'prefix' => false
],
'loginRedirect' => [
'prefix' => 'admin',
'plugin' => 'Articles',
'controller' => 'Articles',
'action' => 'index'
],
'authenticate' => [
'all' => [
'finder' => 'auth',
],
'CakeDC/Auth.ApiKey',
'CakeDC/Auth.RememberMe',
'Form' => [
'fields' => [
'username' => 'email'
]
],
],
'authorize' => [
'CakeDC/Auth.Superuser',
'CakeDC/Auth.SimpleRbac',
],
],
'OAuth' => [
'path' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', 'prefix' => null],
'providers' => [
'facebook' => [
'className' => 'League\OAuth2\Client\Provider\Facebook',
'options' => [
'graphApiVersion' => 'v2.8', //bio field was deprecated on >= v2.8
'redirectUri' => Router::fullBaseUrl() . '/auth/facebook',
'linkSocialUri' => Router::fullBaseUrl() . '/link-social/facebook',
'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/facebook',
]
],
'twitter' => [
'options' => [
'redirectUri' => Router::fullBaseUrl() . '/auth/twitter',
'linkSocialUri' => Router::fullBaseUrl() . '/link-social/twitter',
'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/twitter',
]
],
'linkedIn' => [
'className' => 'League\OAuth2\Client\Provider\LinkedIn',
'options' => [
'redirectUri' => Router::fullBaseUrl() . '/auth/linkedIn',
'linkSocialUri' => Router::fullBaseUrl() . '/link-social/linkedIn',
'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/linkedIn',
]
],
'instagram' => [
'className' => 'League\OAuth2\Client\Provider\Instagram',
'options' => [
'redirectUri' => Router::fullBaseUrl() . '/auth/instagram',
'linkSocialUri' => Router::fullBaseUrl() . '/link-social/instagram',
'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/instagram',
]
],
'google' => [
'className' => 'League\OAuth2\Client\Provider\Google',
'options' => [
'userFields' => ['url', 'aboutMe'],
'redirectUri' => Router::fullBaseUrl() . '/auth/google',
'linkSocialUri' => Router::fullBaseUrl() . '/link-social/google',
'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/google',
]
],
'amazon' => [
'className' => 'Luchianenco\OAuth2\Client\Provider\Amazon',
'options' => [
'redirectUri' => Router::fullBaseUrl() . '/auth/amazon',
'linkSocialUri' => Router::fullBaseUrl() . '/link-social/amazon',
'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/amazon',
]
],
],
]
];
return $config;
/src/Config/permissions.php
<?php
return [
'Users.SimpleRbac.permissions' => [
//admin role allowed to all the things
[
'role' => [GROUP_SUPER_ID, GROUP_ADMIN_ID],
'prefix' => '*',
'extension' => '*',
'plugin' => '*',
'controller' => '*',
'action' => '*'
],
//specific actions allowed for the all roles in Users plugin
[
'role' => '*',
'plugin' => 'CakeDC/Users',
'controller' => 'Users',
'action' => ['profile', 'logout', 'linkSocial', 'callbackLinkSocial'],
],
[
'role' => '*',
'plugin' => 'CakeDC/Users',
'controller' => 'Users',
'action' => 'resetGoogleAuthenticator',
'allowed' => function (array $user, $role, \Cake\Http\ServerRequest $request) {
$userId = \Cake\Utility\Hash::get($request->getAttribute('params'), 'pass.0');
if (!empty($userId) && !empty($user)) {
return $userId === $user['id'];
}
return false;
}
],
//all roles allowed to Pages/display
[
'role' => '*',
//'plugin' => null,
'controller' => 'Pages',
'action' => 'display',
]
]
];
/src/Controllers/Admin/UsersController.php
<?php
namespace App\Controller\Admin;
use App\Controller\Admin\AppController;
use CakeDC\Users\Controller\Traits\ProfileTrait;
use CakeDC\Users\Controller\Traits\SimpleCrudTrait;
use CakeDC\Users\Model\Table\UsersTable;
use Cake\Utility\Inflector;
/**
* Users Controller
*
*
* @method \App\Model\Entity\User[]|\Cake\Datasource\ResultSetInterface paginate($object = null, array $settings = [])
*/
class UsersController extends AppController
{
use ProfileTrait;
use SimpleCrudTrait {
index as protected traitIndex;
add as protected traitAdd;
edit as protected traitEdit;
}
public function index()
{
$table = $this->loadModel();
$authUser = $this->Auth->user();
$conditions = [];
if ($authUser['role'] != GROUP_SUPER_ID) {
$conditions['role !='] = GROUP_SUPER_ID;
}
$tableAlias = $table->alias();
$this->set($tableAlias, $this->paginate($table, $conditions));
$this->set('tableAlias', $tableAlias);
$this->set('_serialize', [$tableAlias, 'tableAlias']);
}
/**
* Add method
*
* @return mixed Redirects on successful add, renders view otherwise.
*/
public function add()
{
$table = $this->loadModel();
$tableAlias = $table->alias();
$entity = $table->newEntity();
$this->set($tableAlias, $entity);
$this->set('tableAlias', $tableAlias);
$this->set('_serialize', [$tableAlias, 'tableAlias']);
if (!$this->request->is('post')) {
return;
}
$entity = $table->patchEntity($entity, $this->request->getData());
$entity->role = $this->request->data('role');
$singular = Inflector::singularize(Inflector::humanize($tableAlias));
if ($table->save($entity)) {
$this->Flash->success(__d('CakeDC/Users', 'The {0} has been saved', $singular));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__d('CakeDC/Users', 'The {0} could not be saved', $singular));
}
/**
* Edit method
*
* @param string|null $id User id.
* @return mixed Redirects on successful edit, renders view otherwise.
* @throws NotFoundException When record not found.
*/
public function edit($id = null)
{
$table = $this->loadModel();
$tableAlias = $table->alias();
$entity = $table->get($id, [
'contain' => []
]);
$this->set($tableAlias, $entity);
$this->set('tableAlias', $tableAlias);
$this->set('_serialize', [$tableAlias, 'tableAlias']);
if (!$this->request->is(['patch', 'post', 'put'])) {
return;
}
$entity = $table->patchEntity($entity, $this->request->getData());
$entity->role = $this->request->data('role');
$singular = Inflector::singularize(Inflector::humanize($tableAlias));
if ($table->save($entity)) {
$this->Flash->success(__d('CakeDC/Users', 'The {0} has been saved', $singular));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__d('CakeDC/Users', 'The {0} could not be saved', $singular));
}
}
如果我直接更改数据库并将字段 "is_superuser" 设置为“1”,则新用户可以正确登录。但是我找不到问题出在哪里。
谢谢。
当调试为真时检查 debug.log 以了解规则评估和调试问题。看起来登录用户(调试来自 $this->Auth->user()
角色的用户数据与您定义的规则不匹配。
还要检查定义权限的正确密钥是 CakeDC/Auth.permissions
请参阅 https://github.com/CakeDC/users/blob/master/config/permissions.php#L53
我会修改规则
[
'role' => [GROUP_SUPER_ID, GROUP_ADMIN_ID],
'prefix' => '*',
'extension' => '*',
'plugin' => '*',
'controller' => '*',
'action' => '*'
],
并将角色更改为*
然后调试用户并匹配角色是正确的。首先检查您是否可以通过此规则访问目标页面,然后开始将规则限制为您需要的内容。