Skip to content

Commit

Permalink
パスワードの複雑性の向上
Browse files Browse the repository at this point in the history
  • Loading branch information
seto1 committed Mar 15, 2024
1 parent 5bf7870 commit e1e224c
Show file tree
Hide file tree
Showing 17 changed files with 244 additions and 65 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@
"install": [
"composer install --no-plugins",
"bin/cake setup install",
"bin/cake install https://localhost [email protected] basercms basercms --host bc-db --username root --password root"
"bin/cake install https://localhost [email protected] baserCMS1234 basercms --host bc-db --username root --password root"
],
"test": [
"bin/cake setup test",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,4 @@ q {}","",""
"27","mail_additional_parameters","","",""
"28","outer_service_output_header","","",""
"29","outer_service_output_footer","","",""
"30","allow_simple_password","0","",""
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,4 @@ q {}","",""
"27","mail_additional_parameters","","",""
"28","outer_service_output_header","","",""
"29","outer_service_output_footer","","",""
"30","allow_simple_password","0","",""
7 changes: 7 additions & 0 deletions plugins/baser-core/config/Seeds/SiteConfigsSeed.php
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,13 @@ public function run(): void
'created' => '',
'modified' => ''
],
[
'id' => '30',
'name' => 'allow_simple_password',
'value' => '0',
'created' => '',
'modified' => ''
],
];
$table = $this->table('site_configs');
$table->insert($data)->save();
Expand Down
21 changes: 20 additions & 1 deletion plugins/baser-core/config/setting.php
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,26 @@
]
]
]
]
],

/*
* パスワードの設定ルール
*/
'passwordRule' => [
// 最小文字数
'minLength' => 12,
// 入力必須な文字種
'requiredCharacterTypes' => [
// 数値
'numeric',
// 大文字英字
'uppercase',
// 小文字英字
'lowercase',
// 記号
// 'symbol',
],
],
],

/**
Expand Down
99 changes: 79 additions & 20 deletions plugins/baser-core/src/Model/Table/UsersTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@
use ArrayObject;
use Authentication\Authenticator\SessionAuthenticator;
use BaserCore\Utility\BcUtil;
use Cake\Core\Configure;
use Cake\ORM\Query;
use Cake\Event\Event;
use Cake\ORM\TableRegistry;
use Cake\Routing\Router;
use Cake\Utility\Hash;
use Cake\Validation\Validator;
use BaserCore\Model\Entity\User;
use BaserCore\View\BcAdminAppView;
Expand All @@ -27,6 +29,7 @@
use BaserCore\Annotation\NoTodo;
use BaserCore\Annotation\Checked;
use BaserCore\Annotation\UnitTest;
use BaserCore\Service\SiteConfigsService;

/**
* Class UsersTable
Expand Down Expand Up @@ -192,22 +195,8 @@ public function validationDefault(Validator $validator): Validator
'provider' => 'table',
'message' => __d('baser_core', '既に登録のあるEメールです。')
]]);
$validator
->scalar('password')
->minLength('password', 6, __d('baser_core', 'パスワードは6文字以上で入力してください。'))
->maxLength('password', 255, __d('baser_core', 'パスワードは255文字以内で入力してください。'))
->add('password', [
'passwordAlphaNumericPlus' => [
'rule' => ['alphaNumericPlus', ' \.:\/\(\)#,@\[\]\+=&;\{\}!\$\*'],
'provider' => 'bc',
'message' => __d('baser_core', 'パスワードは半角英数字(英字は大文字小文字を区別)とスペース、記号(._-:/()#,@[]+=&;{}!$*)のみで入力してください。')
]])
->add('password', [
'passwordConfirm' => [
'rule' => ['confirm', ['password_1', 'password_2']],
'provider' => 'bc',
'message' => __d('baser_core', 'パスワードが同じものではありません。')
]]);

$this->validationPassword($validator);

return $validator;
}
Expand All @@ -229,24 +218,27 @@ public function validationNew(Validator $validator): Validator
}

/**
* validationPasswordUpdate
* validationPassword
* @param Validator $validator
* @return Validator
* @checked
* @unitTest
* @noTodo
*/
public function validationPasswordUpdate(Validator $validator): Validator
public function validationPassword(Validator $validator): Validator
{
$symbol = ' ._-:/()#,@[]+=&;{}!$*';
$quotedSymbol = preg_quote($symbol, '/');

$validator
->scalar('password')
->minLength('password', 6, __d('baser_core', 'パスワードは6文字以上で入力してください。'))
->maxLength('password', 255, __d('baser_core', 'パスワードは255文字以内で入力してください。'))
->add('password', [
'passwordAlphaNumericPlus' => [
'rule' => ['alphaNumericPlus', ' \.:\/\(\)#,@\[\]\+=&;\{\}!\$\*'],
'rule' => ['alphaNumericPlus', $quotedSymbol],
'provider' => 'bc',
'message' => __d('baser_core', 'パスワードは半角英数字(英字は大文字小文字を区別)とスペース、記号(._-:/()#,@[]+=&;{}!$*)のみで入力してください。')
'message' => __d('baser_core', 'パスワードは半角英数字(英字は大文字小文字を区別)とスペース、記号(' . trim($symbol) . ')のみで入力してください。')
]])
->add('password', [
'passwordConfirm' => [
Expand All @@ -255,9 +247,76 @@ public function validationPasswordUpdate(Validator $validator): Validator
'message' => __d('baser_core', 'パスワードが同じものではありません。')
]]);

// 複雑性のチェック
$SiteConfigsService = new SiteConfigsService();
if (!$SiteConfigsService->getValue('allow_simple_password')) {
// 最小文字数
$minLength = Configure::read('BcApp.passwordRule.minLength');
if ($minLength && is_numeric($minLength)) {
$validator->minLength('password', $minLength,
__d('baser_core', 'パスワードは{0}文字以上で入力してください。', $minLength));
}

// 入力必須な文字種
$requiredCharacterTypePatterns = [
'numeric' => [
'name' => __d('baser_core', '数字'),
'pattern' => '\d',
],
'uppercase' => [
'name' => __d('baser_core', '大文字英字'),
'pattern' => '[A-Z]',
],
'lowercase' => [
'name' => __d('baser_core', '小文字英字'),
'pattern' => '[a-z]',
],
'symbol' => [
'name' => __d('baser_core', '大文字英字'),
'pattern' => '[' . $quotedSymbol . ']',
],
];

// 無効な文字種を削除
$requiredCharacterTypes = Configure::read('BcApp.passwordRule.requiredCharacterTypes');
foreach ($requiredCharacterTypePatterns as $key => $name) {
if (!in_array($key, $requiredCharacterTypes)) {
unset($requiredCharacterTypePatterns[$key]);
}
}

// AND条件の正規表現
$patterns = array_map(function($pattern) {
return '(?=.*' . $pattern . ')';
}, Hash::extract($requiredCharacterTypePatterns, '{s}.pattern'));
$pattern = '/^' . implode('', $patterns) . '.*$/';

$validator->add('password', [
'passwordRequiredCharacterType' => [
'rule' => ['custom', $pattern],
'message' => __d('baser_core', 'パスワードは{0}を含む必要があります。',
implode('', Hash::extract($requiredCharacterTypePatterns, '{s}.name'))),
]]);
}

return $validator;
}

/**
* validationPasswordUpdate
* @param Validator $validator
* @return Validator
* @checked
* @unitTest
* @noTodo
*/
public function validationPasswordUpdate(Validator $validator): Validator
{
return $this->validationPassword($validator)
->requirePresence('password', true, __d('baser_core', 'パスワードを入力してください。'))
->notEmptyString('password', __d('baser_core', 'パスワードを入力してください。'));
}

/**
* コントロールソースを取得する
*
Expand Down
99 changes: 82 additions & 17 deletions plugins/baser-core/tests/TestCase/Model/Table/UsersTableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
namespace BaserCore\Test\TestCase\Model\Table;

use BaserCore\Model\Table\UsersTable;
use BaserCore\Service\SiteConfigsServiceInterface;
use BaserCore\TestSuite\BcTestCase;
use BaserCore\Test\Scenario\InitAppScenario;
use BaserCore\Test\Scenario\LoginStoresScenario;
use BaserCore\Test\Scenario\UserGroupsScenario;
use BaserCore\Test\Scenario\UserScenario;
use BaserCore\Test\Scenario\UsersUserGroupsScenario;
use BaserCore\TestSuite\BcTestCase;
use Cake\Core\Configure;
use Cake\Validation\Validator;
use CakephpFixtureFactories\Scenario\ScenarioAwareTrait;

Expand Down Expand Up @@ -141,15 +143,27 @@ public function testValidationDefault()
}

/**
* Test validationPasswordUpdate
* Test validationPassword
* @param $isValid 妥当でない場合、$validator->validateからエラーが返る
* @param $data パスワード文字列
* @param $allowSimplePassword 簡易なパスワードを許可
* @param $passwordRule パスワードの設定ルール
* @return void
* @dataProvider validationPasswordUpdateDataProvider
* @dataProvider validationPasswordDataProvider
*/
public function testValidationPasswordUpdate($isValid, $data)
public function testValidationPassword($isValid, $data, $allowSimplePassword, $passwordRule = [])
{
$validator = $this->Users->validationPasswordUpdate(new Validator());
$siteConfigsService = $this->getService(SiteConfigsServiceInterface::class);
if ($allowSimplePassword) {
$siteConfigsService->setValue('allow_simple_password', 1);
} else {
$siteConfigsService->setValue('allow_simple_password', 0);
}
if ($passwordRule) {
Configure::write('BcApp.passwordRule', $passwordRule);
}

$validator = $this->Users->validationPassword(new Validator());
$validator->setProvider('table', $this->Users);
if ($isValid) {
$this->assertEmpty($validator->validate($data));
Expand All @@ -158,23 +172,74 @@ public function testValidationPasswordUpdate($isValid, $data)
}
}

public static function validationPasswordUpdateDataProvider()
public static function validationPasswordDataProvider()
{
$exceedMax = "testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest";
$exceedMax = str_repeat('a', 256);

return [
// 妥当な例
[true, ['password' => 'testtest', 'password_1' => 'testtest', 'password_2' => 'testtest']],
// 文字数が少ない場合
[false, ['password' => 'test', 'password_1' => 'test', 'password_2' => 'test']],
// 文字数が少ない場合
[false, ['password' => $exceedMax, 'password_1' => $exceedMax, 'password_2' => $exceedMax]],
// 不適切な文字が入ってる場合
[false, ['password' => '^^^^^^^^', 'password_1' => '^^^^^^^^', 'password_2' => '^^^^^^^^']],
// パスワードが異なる例
[false, ['password' => 'testtest', 'password_1' => 'test', 'password_2' => 'testtest']],
// 簡易なパスワードを許可

// - OK
[true, ['password' => 'testtest', 'password_1' => 'testtest', 'password_2' => 'testtest'], true],
// - 文字数が少ない
[false, ['password' => 'test', 'password_1' => 'test', 'password_2' => 'test'], true],
// - 文字数が多い
[false, ['password' => $exceedMax, 'password_1' => $exceedMax, 'password_2' => $exceedMax], true],
// - 不適切な文字が入っている
[false, ['password' => '^^^^^^^^', 'password_1' => '^^^^^^^^', 'password_2' => '^^^^^^^^'], true],
// - パスワードが異なる
[false, ['password' => 'testtest', 'password_1' => 'test', 'password_2' => 'testtest'], true],

// 簡易なパスワードを許可しない

// - OK
[true, ['password' => 'TestPassword1!', 'password_1' => 'TestPassword1!', 'password_2' => 'TestPassword1!'], false, [
'minLength' => 12,
'requiredCharacterTypes' => [ 'numeric', 'uppercase', 'lowercase', 'symbol' ],
]],
[true, ['password' => '1234', 'password_1' => '1234', 'password_2' => '1234'], false, [
'minLength' => 4,
'requiredCharacterTypes' => [ 'numeric' ],
]],
[true, ['password' => 'AAAA', 'password_1' => 'AAAA', 'password_2' => 'AAAA'], false, [
'minLength' => 4,
'requiredCharacterTypes' => [ 'uppercase' ],
]],
[true, ['password' => 'aaaa', 'password_1' => 'aaaa', 'password_2' => 'aaaa'], false, [
'minLength' => 4,
'requiredCharacterTypes' => [ 'lowercase' ],
]],
[true, ['password' => '!!!!', 'password_1' => '!!!!', 'password_2' => '!!!!'], false, [
'minLength' => 4,
'requiredCharacterTypes' => [ 'symbol' ],
]],
// - 文字数が少ない
[false, ['password' => 'TestPassword1!', 'password_1' => 'TestPassword1!', 'password_2' => 'TestPassword1!'], false, [
'minLength' => 24,
'requiredCharacterTypes' => [ 'numeric', 'uppercase', 'lowercase', 'symbol' ],
]],
// - 文字種が少ない
[false, ['password' => '1234', 'password_1' => '1234', 'password_2' => '1234'], false, [
'minLength' => 4,
'requiredCharacterTypes' => [ 'numeric', 'uppercase', 'lowercase', 'symbol' ],
]],
];
}

/**
* Test validationPasswordUpdate
* @return void
*/
public function testValidationPasswordUpdate()
{
$validator = $this->Users->validationPasswordUpdate(new Validator());

$this->assertEmpty($validator->validate([
'password' => 'TestPassword1!', 'password_1' => 'TestPassword1!', 'password_2' => 'TestPassword1!',
]));

$this->assertNotEmpty($validator->validate([]));
}

/**
* Test validationNew
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,8 @@ $(function () {
} else if ($("#admin-email").val() === "") {
alert(bcI18n.message1);
result = false;
} else if ($("#admin-password").val().length < 6) {
alert(bcI18n.message4);
result = false;
} else if ($("#admin-password").val() !== $("#admin-confirm-password").val()) {
alert(bcI18n.message5);
result = false;
} else if (!$("#admin-password").val().match(/^[a-zA-Z0-9\-_ \.:\/\(\)#,@\[\]\+=&;\{\}!\$\*]+$/)) {
alert(bcI18n.message6);
} else if ($("#admin-password").val() === "") {
alert(bcI18n.message2);
result = false;
}
} else if (this.id === 'BtnBack') {
Expand Down
7 changes: 6 additions & 1 deletion plugins/bc-admin-third/src/css/components/_install.scss
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,14 @@
}
}
}
.bca-checkbox__label {
margin-top: 10px;
font-weight: normal;
font-size: 80%;
}
}
.step-5 {
li {
margin:20px 0;
}
}
}
Loading

0 comments on commit e1e224c

Please sign in to comment.