djangoのCreateViewでフォームの初期値を設定する方法

get_initial関数をオーバーライドします。

 

以上、備忘録。

djangoのフォームを扱うビュー3種類

フォーム入力画面を作成するには、

  • CreateViewクラスをオーバーライドする方法
  • FormViewクラスをオーバーライドする方法
  • 関数ビューで自分で書く方法

の主に3種類があります。

以下は、まったく同じ動きをするフォームを、3種類の書き方で書いています。(フォームのクラスはforms.pyで別途定義してあるものとします。)

  • CreateViewクラスをオーバーライドする方法

CreateViewクラスは、FormViewクラスをオーバーライドした、フォームからのデータ登録に特化したクラスです。

単純に入力→保存を行うような機能がめちゃくちゃ簡単にできます。テンプレートは指定がなければ、アプリ名_form.htmlがデフォルトテンプレートとなります。

 

  • FormViewクラスをオーバーライドする方法

CreateViewは値が正しければDBに自動的に登録してくれるクラスですが、FormViewはそのままでは登録までは勝手にしてくれません。

送られた値が正しかった時に他に何かしたい、といった時に使うのがいいのではないかと思います。

 

  • 関数ビューで自分で書く方法

FormViewクラスに比べ、テンプレートへのレンダリングなども含みます。

sessionやcookieに何か保存したり呼び出したりなど、仕様を細かく指定した時には自分で関数ビューを書いた方が良いです。

 

以上、備忘録。

djangoの関数ビューでログイン必須にする

djangoのビューにおいて、クラスビューの場合はLoginRequiredMixinを渡しておけば勝手にログイン必須になるのでいいのですが、関数ビューの場合は引数の制限の関係でこの方法が使えません。

なので、login_requiredクラスを別に読み込んで書く必要があります。

  • クラスビューの場合

  • 関数ビューの場合

 

以上、備忘録。

Djangoのアプリ管理画面でユーザのフルネームを表示させる

フレームワークって、決まったことをやる分にはめちゃくちゃ速く開発出来ちゃうけど、ほんのちょっとここをこうしたいって時に、仕様が理解できてないと、ものすごい時間と労力を取られることがある、、。

Djangoで作成したアプリのモデルを定義すると、管理画面上に自動的にレジスターが出てくるので非常に便利。

でもそのレジスターを一覧表示した時、外部キー(foreignkey)で紐づけたユーザ情報が、デフォルトだとユーザ名(ログインID)になってしまう。

せっかくカスタムユーザモデルを定義したのだから、ここにフルネームを出したい。

カスタムユーザモデルを修正。

マイグレーション忘れずに。

するとアプリのレジスター画面で 以下のように表示される。

とりあえずこれでOK。

ただしUSERNAME_FIELDはユーザのレジスターやアクティベーションに関係してくるので、外部向けの新規ユーザ登録画面などを作った時に、弊害が出てくる可能性も、、、。

もうちょっと勉強が必要かな。

6/13追記:

さっそく弊害出ました。フルネームがユーザ名として扱われるようになったため、管理画面にログインする際のIDもフルネームで判定されるようになってしまいました。元に戻しました、、、。

GmailからエックスサーバへのSMTP接続がTLSエラーになる件

弊社のように、エックスサーバなど外部のメールアドレスをGmailで一括管理している方も多いはず。

ところが4月8日ころから、エックスサーバを介したメール送信が行えない事象が発生。その時点でエックスサーバで特に障害情報などは出ていませんでした。

送信後に以下のようなエラーが返ってきます。

証明書がマッチしないTLSネゴシエーションエラーのようです。Googleのコミュニティでも揉めてますね(笑)。

調べたら、早速詳しくまとめていただいている方がいました。

エックスサーバのSMTPサーバを調べると、証明書のドメイン名は「*.xserver.jp」(ワイルドカード)でしたので、各サーバに割り当てられているsvから始まるサーバ番号がわかればこのドメイン名が分かります。

例えば「sv1234」であれば、証明書のドメイン名「sv1234.xserver.jp」になります。

 

Gmailの設定で、SMTPサーバ名がこの「sv****.xserver.jp」でない場合は、この名前を指定してやれば解決です。

 

今見てみたら、エックスサーバのFAQにもそのように案内がありますね。(最近変わった?)

以上です。

【ECCUBE2】スパム対策としてお問合せフォームにreCaptchaを導入

定期的に中国から来る迷惑なお問合せフォームを利用したスパム。

スパムの一例↓

このように、メールアドレス欄に不特定多数のメールアドレスを指定し、自動返信機能を利用してメールを送り付けている。

今までは接続元IPを特定して、apacheの設定ファイルなり.htaccessで個別にアクセスを拒否するなど、対症療法をしていましたが、業務の負担になりつつあるので、導入することにしました。

結果として効果はかなりあったようで、対策後およそ1か月、未だスパムによる被害は1回もうけていません。

reCaptchaをECCUBE2のお問合せフォームに導入する手順は以下の通りです。

サイトキーとシークレットキーの取得

  1. reCaptchaにアクセスし「Admin console」を開きます。Googleアカウントが必要になります。
  2. 必要事項を入力し、サイトキーとシークレットキーを取得します。(今回は「」を採用します。)

テンプレートを修正

ECCUBE2のお問合せフォーム(確認画面)のテンプレートファイルを修正します。

スマホページも運用している場合はそちらのテンプレート(data/Smarty/templates/sphone/contact/confirm.tpl)も同様に修正します。

PHPファイルの修正

お問い合わせの受付・自動返信メール送信処理を行うPHPファイルを修正します。

確認

確認画面の右下に、以下のようなreCAPTCHAアイコンが表示されていれば、適用完了です。

 

参考サイト)

 

【ECCUBE2】外部からのPOSTでセッションが切れる件の対応

2020年4月に入ったあたりから、ECCUBE2を使用している内部サービスで、決済代行会社の決済画面から戻った際になぜかセッションが無効となり、ページ遷移エラーもしくは自動ログアウトしてしまう現象が発生。

原因は結果的に、chrome80からのCSRF(クロスサイトリクエストフォージェリ)対策として、Cookieセット時にSameSite属性が適切に指定されていない場合、外部からそのサイトにPOSTなどでアクセスされた際に発行されたサイトのCookieが強制的に無効になるという仕様によるものでした。(エンジニアが気づいた)

※なお、多くの混乱を招いたようで、直後のChromeアップデートで当仕様は取り急ぎロールバックされた模様

Googleからのアナウンスは、2019年11月には出ていた模様で、4月に入ったあたりから徐々にクライアントのChromeが80に強制アップデートされたようです。

現実に多くのショッピングサイトでは、決済時に決済代行会社の決済画面(特にリンクタイプ)で決済を行った後、処理結果受け取りのために決済完了画面からPOSTで戻って、パラメタを処理しています。

ECCUBE2のなどのカートシステムなどを利用している場合、大抵はページ遷移チェックがかかるため、この時決済画面に行く前のCookie情報が削除されていることから、セッション情報が判定できず、ログイン状態が無効となりセッションエラーもしくはログアウトという結果になります。

こういったサイトでは、対策として、

  • Cookie発行時に「SameSite=None; Secure」をセットする
  • httpsを利用する

ことで対応できます。

こちらに詳しくまとめていただいている方がいるので、適宜参照していただければと思います。

ECCUBE2のついては、すでにパッチが配布されていますで、ECCUBE2のサイト管理者は至急対応されることをおススメします。

なおこの配布パッチを充てると、具体的には、

  1. Cookieセット時に「SameSite=None;」を併せてセットする。この時、httpsなら「 Secure」を追加する
  2. SameSite=Noneが未対応のブラウザ用に、あらかじめ互換用のCookieを発行しておく。
  3. ECSESSIDが 現Cookieと対応しない場合は ECSESSID の Cookie が拒否されたと見なす
  4. 3の場合はあらかじめ発行しておいた互換用 cookie からセッションデータを読み込む

といった動作を行うようになります。

 

今回のアップデートについて、告知はされていたものの、もう少し具体的に影響を受ける対象事業者に対して大々的に告知してほしかったというのが正直なところ。

さらに言えば、決済代行会社も情報を早めに得て、影響を受ける顧客に周知するべきだったと思います。(リンクタイプを使っているクライアントはかなりいると思うし、、、)

うちが使っている決済代行会社は、通常結構この辺はきっちりしていて、こういう件が発生するときはかなり早めに連絡がくるのですが、今回に限ってはまったくもってノーマークだったように思います。念のため問い合わせたときに「特に障害情報は出ていません。どのような不具合でしょうか?」のような対応でしたからねー。

DKIMの複数ドメイン対応と作成者署名,第三者認証(CentOS7.2+Postfix+OpenDKIM)

Postfix, OpenDKIMはインストール済み、firewallも適切に設定済みであると仮定。

鍵ペアの作成

※複数のドメインを異なるキーペアで認証する場合は上記を繰り返し、必要数分キーペアを作成する。ドメインが異なればセレクタ名は同じでも大丈夫だが、混乱を避けるため変えてもよいと思う。

OpenDKIMの設定

1つのドメインしか扱わない場合

複数のドメインを扱うが、すべて同じキーペアを使う場合

複数のドメイン、複数のキーペアを扱う場合

※上から順に処理されるので、ワイルドカード(ex: *@*, *@*.example.com, *@sub.*)を使うとその下の行は無効になる。ドメインを明示的に指定する場合はワイルドカード行の上に書いておく。

 

キーペアの公開鍵を取得

公開鍵をDNSに登録

①FROMドメインが“example.com”で“example.com”の署名を使い作成者認証する場合は、”example.com”のDNSサーバに公開鍵を登録。

項目
Name selector._domainkey
Type TXT
Value “v=DKIM1; k=rsa; p=MIGfMA0GCS…”

ポリシーが登録されてなければポリシーも登録。

項目
Name _policy._domainkey        
Type TXT
Value “t=y; o=~”
項目
Name _domainkey            
Type TXT
Value “t=y; o=~”

②~③FROMドメインが”hoge.com”で“hoge.com”の署名を使い作成者認証する場合は、”hoge.com”のDNSサーバに公開鍵を登録。

FROMドメインが”任意のドメイン”で“example.com”の署名を使い作成者認証する場合は、任意ドメインのDNSサーバに公開鍵を登録。

⑤~⑥FROMドメインが”fuga.com”で“example.com”の署名を使い第三者認証する場合は“example.com”ドメインのDNSサーバに公開鍵を登録。

⑦FROMドメインが”任意のドメイン”で“dkim.example.com”の署名を使い第三者認証する場合は“dkim.example.com”ドメインのDNSサーバに公開鍵を登録。

項目
Name selector_common._domainkey.dkim
Type TXT
Value “v=DKIM1; k=rsa; p=MIGfMA0GCS…”
項目
Name _policy._domainkey.dkim     
Type TXT
Value “t=y; o=~”
項目
Name _domainkey.dkim         
Type TXT
Value “t=y; o=~”

レコード返却の確認

Postfixの設定

サービス再起動

確認

Gmailが一番わかりやすいので、Gmailでテスト

受信したメールで、DKIMがPassで、ヘッダが以下のようになってればOK。

作成者認証の場合

DKIMSignature: (~略~)
d=example.com;
s=selector;
b=xdIeG4cUHIBhU0nix2V5tK9Z
(~略~)
From: <someone@example.com>        

第三者認証の場合

DKIMSignature: (~略~)
d=example.com;
s=selector;
b=xdIeG4cUHIBhU0nix2V5tK9Z
(~略~)
From: <someone@hoge.com>        

 

参考サイト)

 

ECCUBE3でフォームの入力制限文字数を変更する

例えば、管理画面の何かしらのメニューでURL情報を入力するとき、stext_len(50文字)だと足りない時があるので、mtext_len(200文字)に変更する。

 

これらの値($config[‘***’])は”/src/Eccube/Resource/config/constant.yml.dist”で定義されている。

ちなみに以下、文字数制限の主要なデフォルト値。

ECCUBE3 独自パラメタで検索→リスト表示の時にサブタイトルにパラメタ名を反映させる

前提条件いろいろ割愛しますが、DBに当該データが入っていて、Doctrineファイルにパラメタと名前が定義してあり、Formビルダー各パラメタが構築されてるのが前提です。

以下ファイルを修正。

/src/Eccube/Controller/ProductController.php

基本、$searchDataに値が入っていれば、getName->()でとれます。