管理画面へのアクセスをIPで制限

CakePHPで開発してて、管理画面(admin)へのアクセスはIPで制限したいな

という場合の設定方法

昔、componentとか駆使して設定したことがありますが、もっと簡単な方法がありました。
htaccessを使う方法です。

/webroot/admin のディレクトを作ります。

そのadminディレクトリにhtaccessを置きます。

order deny,allow
deny from all

# 許可したいIP
allow from 1.0.16.0

特定のURLで404エラー!

CakePHPで開発中、ある特定のURLの場合のみ404エラーが発生しました。

一意のURLを生成するためにbase64_encodeなどを駆使して生成したURLで発生。

色々調べてみると…

base64の使用文字
「a-zA-Z0-9+/」
この最後の「/」が問題のようだ。
urlencodeして使用していたけど×

mod_rewriteでURLに「%2F(スラッシュをurlencodeした文字)」が入っていると404を返すらしい。

それを解決するには、「AllowEncodedSlashes On」にすると解決できるそうだ。
これはデフォルトだとOffになっているため、先に%2Fをスラッシュとして認識し、URLが見つからないと404を返すと。。

んじゃ、Onにして解決だね!

と言いたいところだけど、それはちょっと難しい。

これはApacheの設置httpd.confなどで設定するものらしい。
htaccessでは解決できない。
レンタルサーバーなどでは簡単に変更できないので詰んでしまう・・・・

ということで、私は単純にqueryでgetとして送信することで回避させました。

https://zero-one-x.com/xxxx%2Fxxx

↓↓↓↓

サイト

CakePHP4のデバッグツールバーの表示方法

CakePHP4のデバッグツールバーの表示方法
(CakePHP3も一緒なのかな??)

サーバーにアップしたところ、ツールバーが表示されなくなっていたので、その解決方法

まずはマニュアル通り設定をしていきます。

/config/bootstrap.php

下記のようなdebugの設定があります。

if (Configure::read('debug')) {
	Configure::write('Cache._cake_model_.duration', '+2 minutes');
	Configure::write('Cache._cake_core_.duration', '+2 minutes');
	// disable router cache during development
	Configure::write('Cache._cake_routes_.duration', '+2 seconds');

	/** ここに追加します **/
}

「/** ここに追加します **/」に下記の2行を追加します。

// デバッグツールバーの表示
Configure::write('DebugKit.panels', ['DebugKit.Packages' => true]);
Configure::write('DebugKit.safeTld', ['jp']);# jpドメインの表示を許可する

2行目のDebugKit.safeTldの値にご自身のドメインを指定します。

これでデバッグツールバーが画面の右下に表示されると思いますが、
それでも表示されない場合は強制的に表示させる設定を追加してみます。

Configure::write('DebugKit.forceEnable', true);

私の場合これでも表示されませんでした。
ソースを確認するとデバッグツールのタグを出力されていました。
コンソールを確認してみると下記のエラーメッセージが表示されてました。

toolbar.js?1678925804:54 Mixed Content:
The page at ‘https://xxxxxxxxxx.jp’ was loaded over HTTPS,
but requested an insecure frame ‘http://xxxxxxxxxx.jp/debug-kit/toolbar/xxxxx-xxxxx-xxxxx’.
This request has been blocked; the content must be served over HTTPS.

SSLじゃないのでブロックしたと。

この情報をもとに検索
下記の修正案がありました。

参考
https://github.com/cakephp/debug_kit/issues/736

上記の記事を参考に修正していきます。

vendor/cakephp/debug_kit/src/ToolbarService.php

public function injectScripts($row, ResponseInterface $response)
{
...
        $url = Router::url('/', true);
+        if (isset($_SERVER['HTTPS']) || isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
+            $url = str_replace('http', 'https', $url);
+        }

※「+」が追加する行

vendor/cakephp/debug_kit/templates/Requests/view.php

<?php $this->Html->script('DebugKit./js/debug_kit', [
    'block' => true,
    'id' => '__debug_kit_app',
    'data-id' => $toolbar->id,
-    'data-url' => Router::url('/', true),
+    'data-url' => checkHttps(Router::url('/', true)),
    'data-webroot' => $this->request->getAttribute("webroot"),
]) ?>
+<?php
+function checkHttps($url) {
+    if (isset($_SERVER['HTTPS']) || isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
+        $url = str_replace('http', 'https', $url);
+    }
+    return $url;
+}
?>

※「+」が追加する行 「-」は削除する行

これで自ドメインがSSLならSSLでデバッグツールのURLを発行してくれます。

CakePHP4 手動でパスワードチェックする方法

$this->Auth->identify();

上記を使うと送信されたデータとDBから抽出したデータをチェックするのを自動でやってくれます。
手動でやりたい場合は上記は使えません。

下記のコードで手動でチェックできます。

use Cake\Auth\DefaultPasswordHasher;

$hasher = new DefaultPasswordHasher();
// パスワードチェック
if($hasher->check('素のパスワード', 'ハッシュ化されたパスワード')){
	// パスワードOKの処理
}else{
	// パスワードNGの処理
}

[CakePHP]バリデーションではまった話

CakePHP4のバリデーションではまった話

バリデーションのalphaNumericが日本語をはじかないというので
preg_matchで実装しようとしたら動作しなくて困った

最初は下記のように書いたら「The provided value is invalid」のエラーが発生

$validator
	->scalar('password')
	->add('password', 'custom', [
		'rule' => function ($value) {
			return preg_match("/^[0-9a-zA-Z]{4,16}$/", $value);
		},
		'message' => '4桁以上16桁以下の英数字で入力してください。',
	]);

色々調べてみると・・・
https://www.php.net/manual/ja/function.preg-match.php

preg_matchの戻り値
マッチした場合は1
マッチしなかった場合は0
失敗した場合はfalse

そう。マッチしない場合はfalseではない。
なので上記に書いたコードだと動作しない。

下記のように書き換えて動作確認できた!

$validator
	->add('password', 'custom', [
		'rule' => function ($value) {
			$result = preg_match("/^[0-9a-zA-Z]{4,16}$/", $value);
			if($result == 1){
				return true;
			}

			return false;
		},
		'message' => '4桁以上16桁以下の英数字で入力してください。',
	]);

戻り値をifで判定してreturnでちゃんと戻す。

これで1日悩んでました。

[CakePHP]ダウンロード後にページをリロードしたい

データをダウンロード処理したときにフラグを立てるなど色々処理をしている。
ダウンロード後にリダイレクトかリロードをしたいと思った。

ダウンロードの処理でheaderを使っているのでリダイレクトのLocationが使えない。

そこでJSで別ウインドを開いて、そこにダウンロード処理を渡す。
その処理の後にページをリロードする処理をしてあげるとOK。

$(function(){
	// ダウンロードボタン
	$('#order_export_btn').on('click', function() {
		window.open('<?= $this->Url->build(["controller" => "Hoge","action" => "download"], ['fullBase' => true]); ?>');// URLを開く
		setTimeout(reload, 1000);// 1秒後にリロード実行
	});
});

// ページリロードの処理
var reload = function(){
	location.reload(true);
};

リダイレクトしたい場合はreloadのところをhrefにするとOK

// リダイレクトの処理
var reload = function(){
	location.href = "https://zero-one-x.com/";
};

【未解決】CakePHP4のログアウト時のセッション削除

CakePHP4でログイン機能Authのログアウト時にセッションが削除できない問題

未解決ですが情報記載します。

ログアウト処理時にセッションのdestroyを行うとログイン情報が削除できないのです。


$this->Auth->logout();
$this->session->destroy();

Auth->logoutのみ
 同列のセッション情報が生きている
session->destroyを追加
 Authのログイン情報が生きている

Auth->logoutはAuth配下のセッション情報は削除できるが、Authと同列のものは削除できていない。
そこで直接Session->destroyを行うと、同列のものは削除できたがAuthの情報は削除できずに残っていた。

調べてみても情報なし。
しょうがないのでdeleteで個別に削除


$this->Auth->logout();
$this->session->delete("Data");
$this->session->delete("HogeHoge");

ちなみにPHP関数でsession_destroyだとエラーでした。

CakePHP4のFormヘルパーでDivタグの削除

CakePHP4のフォームヘルパーでDIVが削除できなくて困った。
DIVのオプションがなくなったようです。

CakePHP3からなくなったのかな?
CakePHP3のやりかただと削除できなかったので、CakePHP4のマニュアルに載っているやり方で削除します。

フォームヘルパーのテンプレートで対応

$this->Form->create($article)."\n";
$myTemplates = [
    'inputContainer' => '{{content}}',
];
$this->Form->setTemplates($myTemplates);

マニュアル
https://book.cakephp.org/4/ja/views/helpers/form.html#formhelper

個別にできないのは結構不便。
他にやり方があるのだろうか・・・