例による実践的な Web ベースの深層学習とセキュリティ

Daisyのプロフィール写真

による Daisy

実用的なWebベースの深い学習とセキュリティの例 第3版 シャーロット・ハーパー 2024年7月3日 序文: Web向けのソフトウェアの構築におけるセキュリティ上の考慮事項は、信頼できる、安定しており、実用的な目的に役立つプロトタイプを設計しながら、Web開発者の計画と実行の重要な部分です。 HTML、JavaScript、およびCSSの実装と、Python、C/C ++、Java、Bashを実装するバックエンドソフトウェアの実装により、Dom(Document Object Markup)は、Web開発者に自由と力を提供し、さまざまなプロジェクトを作成する自由と力を提供します。創造性、使いやすさと機能性を提供し、謙虚さと性格を描写し、使いやすさを提供するだけでなく、平均的なジョーにとって魅力的な利便性と重要なサービスを提供します。時間を殺したり、インターネットで何かを成し遂げたりするには、通常はタッチスクリーンのスマートフォンデバイスで。ほとんどの人は、ゼロからウェブサイトを構築したいときにどこから始めればよいかさえ知らないでしょう、彼らは、他の人のウェブサイトで開始し、機能性、信頼性、使いやすさ、特に創造性が制限されたものを構築する傾向があります。特にソフトウェアへの高価なサブスクリプションのためにお金を払うお金を無駄にする人は、使いやすさと柔軟性の制限を考えると、とにかく使用したい人はほとんどいません。この本を読んで、私があなたに教えたいことを学んだり、あなたの目標について個人的に話したり、正しい方向に何らかのガイダンスを取得したり、自分のソフトウェアをコードして書くことを学ぶ意欲がある場合は、この本を家に持ち帰り、次の影響力のある、強力で、合理化された、重要なWebアプリケーションを構築するために時間を確保します。 私について: 私は広いソフトウェア開発者ですC/C ++、Java、Python、HTML、CSS、JavaScriptの経験のAnge。私は人々が使用し、訪問したい、さらには時間を学び、再作成し、殺すために使用することに夢中になりたいウェブサイトを構築し、最も重要なことに、私はソフトウェアを販売しています。あなたがウェブサイトをどのように見て機能させたいかについて正確に考えていたなら、あなたは私をサポートすることをいとわなかったので、私はあなたに会っている間、私自身のニーズを満たすことができ、あなたは自分でウェブサイトを運営するコストを賄うことをいとわないでしょう。次のYouTube、Tiktok、Twitter、Google、またはアクセスできるハイテクセキュリティアプリでさえ構築します。私の時間を売ろうとする代わりに、私はあなたの時間を買おうとしています:私はあなたにすでに存在する情報を自分でアプリ(ウェブサイト)の構築に話したいと思います、そしてあなたがあなたが独立したソフトウェア開発者になるために必要なものを教えてください、起業家は、あなたが望むあらゆる分野で成功したキャリアをリードしています。そして、私を明確にさせてください、私があなたに与える教育は非公式になります。あなたは学校に行って、これらすべてをで学ぶことができますRMAL教育、または学校でこの本を読んで、あなたの課題を完成させ、あなたの教育から多くを取り除いてください。しかし、私は正式にあなたを熱い席に置いて、課題を完了するように頼むことはありません。私はあなたの教授ではありません。あなたはあなた自身の個人的な成功に駆り立てられたキャリアに向けてあなたを導きたい友人のように私を考えることができます。そして、私もあなたに成功を売っていません、あなたはあなたの時間とともにそれを買う必要があります。コードの学習には急な学習曲線があり、決して簡単ではなかったか、そうあるはずです。自分でアプリを学び、構築するためにイライラしている場合でも、できる限り一生懸命働き、失敗し、再試行し、再試行する必要があります。それはコード自体の性質です。コードは、プログラマーエラーメッセージを提供するように設計されたコンパイラによって実行されます。これらは、検索エンジンにエラーをコピーして他の人の例を読むだけでも、コードの方法を教えます。そして、私は言わなければなりません、あなたは非常に金持ち、賢く、成功する必要はありませんアプリを構築するために詳細指向または整理されています。コンピューターはあなたのためにその組織の世話をします。試行錯誤を通して忍耐し、焦点を維持し、自分がしていることに一生懸命働く必要があります。そして、あなたはあなたがしていることの全体で非常に成功したキャリアを持っているでしょう。 私という人間: 最後のセクションは学習に関するものであり、あなたがこの本からの方法をとることについてのことを理解しています。私は正確に誰ですか?それは複雑な質問です。私は自分自身が不明です。私は時々この本をコーディングしたり書いたりすることを困難にすることができる病状に苦しんでいるので、自分自身を紹介することになると私の人生をより困難にする社会化とアイデンティティの問題に課題を提示します。要するに、あなたがこの本を読んでいるなら、あなたはそれをひっくり返してそれが役に立つと思ったので、あなたがそれを家に持ち帰りました、またはあなたがあなたにとってあなたにとって私はあなたが成功するのを見たいと思っているような心のある個人ですあなたがすることすべて。私は自分自身、ソフトウェアです開発者と学生、そして私は、ソフトウェアのハンドブックを手に入れたいと考えている他の学生のためにこの本を書いています。 、有用で、大規模で、機能的で、まとまりがあり、魅力的なアプリがあり、ビジネスラインに関係なく成功を促進できます。主に、これが私がしていることです。私は自分自身や他の人々が成功するのを助けるためにアプリを構築します。私も著者ですが、これは私の最初の出版物であり、ポートフォリオを有用なドキュメントにまとめるために完了するつもりです。私もアーティストです。 私はあなたにこれを認めます、私はちょっと奇妙な人です。私は完璧ではありません。私は、大学を去り、州を去ることを導いて、より多くの成功を収めて自分の名前を作ろうとする法律にさえ告げました。私は出生時の女性で、化粧をし、自分の写真を撮り、ドレスや他の女性の服を着て、自分を意識し続けています本質的に男性。私は過去に他の人たちに、WebAppsの執筆と構築に苦労することにつながる問題がありました。この本を早く手に入れることができなかったことをお詫びします。あなたはこれが必要でした。あなたは私のように見え、私のように機能し、同じことをするコードを読み、書きたいと思うでしょう。それのために、あなたはあなたの人生で成功するために必要なリソースを持っています。私は家族の育ち、健康状態、医師、メディア、法律にあらゆる種類の問題を抱えており、私のコードは、分裂した欲求不満の世界でフェミニズムと女性の性質である闘争を深く反映しています。しかし、この本は私が深く気にかけているもの、私の赤ちゃん、私のポートフォリオ、そして私の生計を立てるので、私から学ぶためにあなたがテキストを家に持ち帰り、慎重にそれを熟成させるときのあなたの考慮に感謝します。私は完璧ではないことに留意してください、本にはエラー、改訂、新しいエディションがあり、私の執筆で成功した経験を積むために、あなたの論理的な脳をできる限り最高の脳で考える必要があります。また、あなたが書くときに挑戦に直面しているときでさえ、私はあなたにとって良いことを意味することを理解してください。このように考えてみてください。コンピューターシステムをレンタルして、デジタルスペースで想像できることを実行し、遭遇するすべての情報を保存し、#$%!Yzeと整理し、それを理解するようになります。必然的に、あなたが摂取している情報や公開さえも困難に遭遇します。私は同じ困難に遭遇したので、私はあなたにこれを言います。この本をあなた自身の責任で使用し、コミュニティやコミュニティと協力して安全な設定内でソフトウェアを構築し、間違った方法で失敗したり成功したりしても個人的に物事を取り入れないでください。 、そしてなぜ私はあなたにこのテキストを持ってきて、あなたが去る狂気の道に分岐することなくあなたが成功するのを助けることができる理由私たちが働くネットワークのパラレリスティックグローバルスケール、インターネットのおかげで、誰もが世界規模で行う通常の問題に遭遇している間、私は台無しに、破れ、擦り切れました。あなたは私がほんの少しの言葉を持っている人にあまり慣れていないかもしれませんが、私はあなたが読むことをお勧めします、あなたはあなたがあなたの仕事を完了するためにあなた自身のプロジェクトを構築しながら私を読み続けて理解し続けながら私を知るようになります。あなたの教授や教師があなたに割り当てられない限り、この本には宿題はありませんが、あなたが一緒に読んだときに自分でプロジェクトのポートフォリオを構築することを強くお勧めします。学んだことを適用してください。私のCapstoneプロジェクトは、以前のプロジェクトのコード、手作業で整然と書くことを学んだコード、そして私を助けた幅広いアイデアとヒントを学んだコードを組み込んでいるため、この本で読むもののほとんどの基礎です。単純なアプリをスピンアップできるポイントに成功しますUllyは、インターネットで、またはあなたに宣伝されている、またはニュースで、あなたの友人や家族を使用している人気のあるアプリのように機能し、外観と振る舞いをしています。 この本は何ですか: この本は、例ともチュートリアルです。ここでコード、コードの学習方法の手順、コードのデバッグとエラーの修正に関する情報、手順のトラブルシューティング、コードのバックアップと保存方法の手順、コードを破損した場合、コードを保護し、展開し、展開あなたのコードは、面白く、魅力的で、中毒性のあるインタラクティブなWebサイトを構築します。あなたが構築するソフトウェアは、あなたのウェブサイトの訪問者であるエンドユーザーにとって、可能な限り最も魅力的であるために絶対的な最善の光になります。この本では、プラットフォームとセキュリティとしてのWebに焦点を当てたソフトウェアデザインの多くの例を示します。基本を構築することにより、学習体験を開始しますバックアップとスクリプト機能を備えたUnixシェルを使用しています。次に、基本的なブログWebサイトを調べ、写真とビデオ機能をブログにアップグレードし、これらの機能を使用してフリーソフトウェアを使用してセキュリティソリューションを使用し、プラグ可能な認証モジュール(PAM)を使用してサーバーを保護します。次に、ファイルの処理と処理、ビデオ編集、音声寄付、バーコードスキャン、光学文字認識などの概念を確認します。途中で、無料で有料のオプションを使用して、ソフトウェアをより便利かつ安全にするのに役立つAPIを調べます。途中で、バレルとリピーターの設計、砲塔とドローンの設計、その他のプリンシパルなど、銃器や軍需品の設計と製造などの物理的なセキュリティや過激派のツールを探索します。自己防衛と弾力性を示します。ゲームを構築するために途中で休憩を取ります、2Dと3Dエンジンを獲得し、基本的な寸法レンダリングソフトウェアとシリコンゴムでそれぞれ電子振動マッサージャーキャストのケーススタディの例で埋め込まれたハードウェアを使用します。途中で、ソフトウェアをよりよく保護するために、すでに利用可能な機械学習ソリューションも採用します。また、プロセスを合理化および保護するために、Webで利用可能なストックツールを使用します。この本は、Webアプリケーションを構築し、コンピューターおよび組み込み機械システムの専門的なネットワークと統合することに成功するためのガイドであり、全体的なソフトウェアと埋め込みハードウェアの構築ガイドと、背景知識や以前の経験のないガイドです。 この本はそうではありません: 本当にウェブサイトを持ちたい場合は、単純なストアをセットアップして必要なものを販売したり、ブログを投稿したり、写真やビデオを投稿したり、コードを1行に書いたりすることなく、その他のコードを書くことなく、単純なストアを販売するだけです。この本はそうではありません。この本は、より便利で完全にソフトウェアを構築する方法を教えてくれますまだプロトタイプである最新のソフトウェアを展開しているため、古い企業が運営しているスケールで実行するのに費用がかかり、後方の複雑な企業にアピールしていないため、既に見つけられるあらゆるソフトウェアよりも機能的で安全な状態があります。本当に何もしていない人のためにお金を稼ぎます。この本に密接に従うと、コードを書き、調査コードを作成し、独自のアプリを作成すると、自分がしていることからお金を稼ぐことができます。私はこの本から、人々が必要としたい情報が含まれており、私のアプリを購入または使用するときにすでに購入しているため、この本からお金を稼ぎます。この本はあなたのためのアプリを構築するものではありませんが、正しい方向に向けて、必要なツールと、Web用のソフトウェアの構築におけるあなた自身の成功を促進するスキルとヒントをあなたに武装させます。コードあなたは例として記述する必要があり、あなたとあなたのサポーター、ゲスト、顧客、ソフトウェアにまとめる準備ができています、Iends、家族、訪問者、請負業者、およびインターネットの人々は、使用とサポートを望んでいます。 あなたが学ぶこと: この本は、ソフトウェア、本当に機能的で有用なソフトウェア、メディア録音、顔認識などのセキュリティ機能、マシン読み取り可能なゾーンバーコードスキャン、Web APIのようなセキュリティ機能、ビデオと写真を認証、記録、レンダリングする方法、Bluetoothなどのメッセージの交換方法を教えてください。および近接フィールド(NFC)コミュニケーション。この本は、ネットワーク化されたコンピューターを使用する方法、Debian Linuxに焦点を当てた方法、Bashコードを構築する方法、ソフトウェアのインストールとバックアップをシームレスで自動化されたそよ風にする方法、ダイナミックメッセージ、スタイルを提供するためのバックエンドとしてPythonコードを構築する方法を教えてくださいブートストラップを使用してCSSスタイルを使用して、ネットワーク化されたデバイスを介してユーザーログインとインタラクティブ性を有効にし、インタラクティブなメディアや他のWebサイトとネットワークを構築して、検証用のテキストメッセージなどのセキュリティ機能を提供する目的、IDスキャン、画像およびビデオモデレーション、データソフトウェアを安全に保つためのnsaction、支払い処理、暗号通貨取引、非同期タスクなど。バッテリー、充電器、マイクロコントローラー、サーキット、モーター、センサーを使用して、はんだ、ワイヤー、3Dプリント、および鋳造材料を使用して、独自のBluetoothデバイスを構築する方法を学びます。添加剤の製造とツールとダイアキングに適用される3D設計プリンシパルを実証します。そのため、統合されたバッテリー、充電器、電子回路、機能出力を備えた独自の埋め込みハードウェアデバイスを製造できます。そして、それらをBluetoothとWebでネットワーク化します。具体的には、2つのケーススタディ、振動するマッサージャーと自家製の銃器を調べます。どちらも、グラフィカルインターフェイスまたはコマンドラインユーティリティとして利用できるOpenSCADでプログラムされ、より迅速な結果のためにWebに統合できます。 あなたは、以前の経験なしでゼロからウェブサイトを構築して展開する方法を学び、それを機能的で、安全で、美しく、最も便利にします携帯的に実用的です。機械学習とコンピュータービジョンを使用してサイトを安全で実用的なものにし、ウェブサイトからビデオとオーディオを記録し、音楽を寄付し、音楽を作り、有用なサンプルを作成し、ノイズを突破する方法を学びます。他のWebサイトを活用して、提供しなければならないすべての有用な情報を共有し、さらに重要なことに人々をソフトウェアやビジネスに連れて行くために、あなたがあなたのウェブサイトに直接リンクできるウェブサイトの最高のネットワークを構築することです。この本は、メディア、セキュリティ、機械学習に最も焦点を当てています。これは、適切なユーザーを引き付け、現実的で実用的な方法で間違ったソフトウェアを外すことで、Web向けのソフトウェアを構築するのに役立つ主要な3つのコンポーネントです。自動的で頑丈な間、実践と魅力的です。 この本は、UNIX、特にDebian(Ubuntu)、Bash Shell、Python、HTML、CSS、JavaScript、および多くの便利なソフトウェアパッケージを教えています。リクエストと同様に、GitやFFMPEGなどの便利なBASHソフトウェアも同様です。また、暗号通貨を自動的に取引する方法を教え、暗号通貨や通常のデビットカードから支払いを行いながら、そうすることを選択した場合は、訪問者に収益のシェアを支払います。広告を通じてあなたのウェブサイトからお金を稼ぐ方法、検索エンジンのアプリを準備し、迅速にする方法を教えます。顧客があなたを見つけるために検索するものの最初のランキングにランク付けされ、多くの一般的なランキングでランク付けされます可能な限り検索します。ソフトウェアを販売したり、宣伝したり、サービスを探しているクライアントにアピールしたり、すでに存在し、安価でうまく機能する道を通してインターネット上で自分の名前を作る方法を教えます。あなたのために働くクラウドコンピューターにデータを保存し、あなたのデータを安く保存する方法、あなたのユーザーが望むこととあなたが望むことを行うウェブサイトを計画して構築する方法、そしてあなたのユーザーをパッティングすることによってあなたのエンゲージを維持する方法を教えますサイトAタップは、通知、電子メール、テキストメッセージ、電話、その他の手段を使用して、ユーザーを自由に使用できるようにして、ユーザーを自由に使用できるようにします。この本は、メディアをテキストから写真、ビデオ、オーディオまで、メディアを大量に公開して配布することの実用性に焦点を当て、エンドユーザー(顧客)に良い印象を与え、作成するために自分自身を販売することに焦点を当てます。あなたとあなたのみを代表し、あなた、あなたのソフトウェア、あなたの会社を可能な限り最高の方法で見栄えを良くするウェブサイト、アプリ。また、コーディングのヒント、メイクアップや写真などの実用的な虚栄心、モデリングや演技など、私からいくつかのヒントとトリックを学びます。ソフトウェアをにもたらすために、プラットフォームの健全なバランスをとって必要なだけのコンテンツを配布しながらあなたに必要以上に努力、仕事、またはお金のないルーション。 この本は、「実用的なWebベースの深い学習と例による例」と呼ばれています。理由は、特にWeb向け、特にセキュリティに焦点を当てて、実用的な観点からセキュリティに焦点を当てて、機能するコードの例を使用して、コードをコードすることを扱っています。テキストで概説されている実用的な目的。このテキストの学習コンポーネントには、機械学習、コンピュータービジョン、顔認識、画像とビデオのモデレーション、画像の強化、解像度の強化、画像キャプション、およびその他のタスクを処理するWebで実行する方法を紹介します。本物のコンピューターに伝達された画像、または光学コピー(画像の写真、または印刷された写真)としての画像の性質など、画像から供給された予測メトリック。機械学習は、Webセキュリティとソフトウェアセキュリティに関しては非常に重要です。これは、それ以外の場合は不可能なタスクをプリフォームすることができるためです。あなたのコンピュータはそうかもしれませんあなたはパスコードを使用していますが、顔でログインする場合、使用する方が安全かもしれません。サーバーコンピューターをこの安全なものにすることができます。通常、ユーザー名とパスコードを要求してパスコードを要求してログインすることができます。たぶん、新しいログインまたは新しいIPアドレスの確認トークンがありますが、大規模に構築している場合は、簡単です。基本的に安全で強力なソフトウェアを使用して、これで十分かもしれません。電子メールサービスやテキストメッセージサービスなど、他の人のソフトウェアに密接にソフトウェアを結び付けるだけで、ソフトウェアを安全にしたり、誰か(使用するサイト)を安全にしたりするには十分ではありません。 完璧に安全なソフトウェアを構築する人は誰でも、これが意味することのある程度の感覚を持っています。ソフトウェアは本質的に安全ではありません。なぜなら、アクセスに使用するデバイスとアカウントは、常に自由に自由に使えるとは限らず、ソフトウェアを意図していない人の手に渡る可能性があるため、ソフトウェア自体にリスクをもたらす可能性があるためです。これはこの本の焦点です。ネットワーク化されたコンピューターはデフォルトですWebサーバーは、サーバー自体で実行されている最先端のセキュリティツールを提供するため、長いキートークンとSSHまたはセキュアーシェルキーで固定されており、Webサーバーでセキュリティが最適です。 Webサーバーは、ユーザーがネットワークソフトウェアにアクセスできる場所であるため、ユーザーのデバイスの最も強力な部分であるユーザーのWebブラウザにアクセスできます。このツールキットは、テキスト、表示されているWebページをレンダリングでき、画像、オーディオ、ビデオ(顔や状態IDの写真など)を録画したり、Bluetoothラジオデバイスに読み書きしたり、近いフィールドに読み書きできることもできます。トランスポンダータグ、安価なキーカード、FOB、ステッカー、リング、さらには、Webサイトに結び付けられたWebサーバーによって生成および検証されたデータで読み書きできる一意のシリアル番号を備えたチップインプラント。自由に使えるすべてのツールを使用して、この本を使用して、安全なWebサイトを構築するための知識を身に付けます。あなたのために働くネットワーク化されたコンピューターシステム、あなたの入札を行い、見た目も感じも正しいと感じます。 どこから始めるか: 特に、この本でコーディングの経験がある場合、またはこの本で詳細に説明する前述のツールのいずれかで、この本または任意のセクションで必要なコードを開始するセクションをスキップすることを歓迎します。同様に、ユースケースとその実用的な例を文書化します。コードを書く経験がない場合は、この本をすべて読むことを強くお勧めします。特に、この本があなたに合っていることを確認するために、前のセクションを読むことをお勧めします。この本があなたに合っていない場合は、Web開発自体について学ぶことに興味があるかもしれない友人や親relativeにそれを贈ることを検討し、それを借りて、私があなたを失敗させたギャップを埋めるために彼らから学ぶことを検討してください先生、または他の教師は私の前にしました。あなたがするところから始めて、あなたが便利なものを構築するつもりなら、この本のすべての部分が役立つでしょうpp、そして最高のアプリはエンドユーザーを念頭に置いて構築されていることを考...
例による実践的な Web ベースの深層学習とセキュリティ

実用的なWebベースの深い学習とセキュリティの例 第3版 シャーロット・ハーパー 2024年7月3日 序文: Web向けのソフトウェアの構築におけるセキュリティ上の考慮事項は、信頼できる、安定しており、実用的な目的に役立つプロトタイプを設計しながら、Web開発者の計画と実行の重要な部分です。 HTML、JavaScript、およびCSSの実装と、Python、C/C ++、Java、Bashを実装するバックエンドソフトウェアの実装により、Dom(Document Object Markup)は、Web開発者に自由と力を提供し、さまざまなプロジェクトを作成する自由と力を提供します。創造性、使いやすさと機能性を提供し、謙虚さと性格を描写し、使いやすさを提供するだけでなく、平均的なジョーにとって魅力的な利便性と重要なサービスを提供します。時間を殺したり、インターネットで何かを成し遂げたりするには、通常はタッチスクリーンのスマートフォンデバイスで。ほとんどの人は、からウェブサイトを構築したいときにどこから始めればよいかさえ知らないでしょうスクラッチ、彼らは他の人のウェブサイトで開始し、機能、信頼性、使いやすさ、特に創造性に限定されたものを構築する傾向があります。 、特にソフトウェアへの高価なサブスクリプションのためにお金を払うお金を無駄にして、使いやすさと柔軟性の制限を考えると、とにかく使用したい人はほとんどいません。この本を読んで、私があなたに教えたいことを学んだり、あなたの目標について個人的に話したり、正しい方向に何らかのガイダンスを取得したり、自分のソフトウェアをコードして書くことを学ぶ意欲がある場合は、この本を家に持ち帰り、次の影響力のある、強力で、合理化された、重要なWebアプリケーションを構築するために時間を確保します。 私について: 私はソフトウェア開発者ですC/C ++、Java、Python、HTML、CSS、JavaScriptの経験の範囲。私は人々が使用し、訪問したい、さらには時間を学び、再作成し、殺すために使用することに夢中になりたいウェブサイトを構築し、最も重要なことに、私はソフトウェアを販売しています。あなたがウェブサイトをどのように見て機能させたいかについて正確に考えていたなら、あなたは私をサポートすることをいとわなかったので、私はあなたに会っている間、私自身のニーズを満たすことができ、あなたは自分でウェブサイトを運営するコストを賄うことをいとわないでしょう。次のYouTube、Tiktok、Twitter、Google、またはアクセスできるハイテクセキュリティアプリでさえ構築します。私の時間を売ろうとする代わりに、私はあなたの時間を買おうとしています:私はあなたにすでに存在する情報を自分でアプリ(ウェブサイト)の構築に話したいと思います、そしてあなたがあなたが独立したソフトウェア開発者になるために必要なものを教えてください、起業家は、あなたが望むあらゆる分野で成功したキャリアをリードしています。そして、私を明確にさせてください、私があなたに与える教育は非公式になります。あなたは学校に行って、これらすべてをで学ぶことができます正式な教育、または学校でこの本を読んで、あなたの課題を完成させ、あなたの教育から大いに奪うことさえありますが、私は正式にあなたを熱い席に置いて、課題を完了するように頼むことはありません。私はあなたの教授ではありません。あなたはあなた自身の個人的な成功に駆り立てられたキャリアに向けてあなたを導きたい友人のように私を考えることができます。そして、私もあなたに成功を売っていません、あなたはあなたの時間とともにそれを買う必要があります。コードの学習には急な学習曲線があり、決して簡単ではなかったか、そうあるはずです。自分でアプリを学び、構築するためにイライラしている場合でも、できる限り一生懸命働き、失敗し、再試行し、再試行する必要があります。それはコード自体の性質です。コードは、プログラマーエラーメッセージを提供するように設計されたコンパイラによって実行されます。これらは、検索エンジンにエラーをコピーして他の人の例を読むだけでも、コードの方法を教えます。そして、私は言わなければなりません、あなたは非常に金持ちで賢くなる必要はありません、Assful、または詳細指向または整理さえ、アプリを構築するために整理されています。コンピューターはあなたのためにその組織の世話をします。試行錯誤を通して忍耐し、焦点を維持し、自分がしていることに一生懸命働く必要があります。そして、あなたはあなたがしていることの全体で非常に成功したキャリアを持っているでしょう。 私という人間: 最後のセクションは学習に関するものであり、あなたがこの本からの方法をとることについてのことを理解しています。私は正確に誰ですか?それは複雑な質問です。私は自分自身が不明です。私は時々この本をコーディングしたり書いたりすることを困難にすることができる病状に苦しんでいるので、自分自身を紹介することになると私の人生をより困難にする社会化とアイデンティティの問題に課題を提示します。要するに、あなたがこの本を読んでいるなら、あなたはそれをひっくり返してそれが役に立つと思ったので、あなたがそれを家に持ち帰りました、またはあなたがあなたにとってあなたにとって私はあなたが成功するのを見たいと思っているような心のある個人ですあなたがすることすべて。私は自分自身がエンジニアです、開発者と学生、そして私は、ソフトウェアのハンドブックを手に入れたいと考えている他の学生のためにこの本を書いています。 、有用で、大きく、機能的で、まとまりがあり、魅力的なアプリがあり、ビジネスラインに関係なく成功を促進できます。主に、これが私がしていることです。私は自分自身や他の人々が成功するのを助けるためにアプリを構築します。私も著者ですが、これは私の最初の出版物であり、ポートフォリオを有用なドキュメントにまとめるために完了するつもりです。私もアーティストです。 私はあなたにこれを認めます、私はちょっと奇妙な人です。私は完璧ではありません。私は、大学を去り、州を去ることを導いて、より多くの成功を収めて自分の名前を作ろうとする法律にさえ告げました。私は出生時の女性で、化粧をし、自分の写真を撮り、ドレスや他の女性服を着て、自分を意識し続けています本質的に女性。私は過去に他の人たちに、WebAppsの執筆と構築に苦労することにつながる問題がありました。この本を早く手に入れることができなかったことをお詫びします。あなたはこれが必要でした。あなたは私のように見え、私のように機能し、同じことをするコードを読み、書きたいと思うでしょう。それのために、あなたはあなたの人生で成功するために必要なリソースを持っています。私は家族の育ち、健康状態、医師、メディア、法律にあらゆる種類の問題を抱えており、私のコードは、分裂した欲求不満の世界でフェミニズムと女性の性質である闘争を深く反映しています。しかし、この本は私が深く気にかけているもの、私の赤ちゃん、私のポートフォリオ、そして私の生計を立てるので、私から学ぶためにあなたがテキストを家に持ち帰り、慎重にそれを熟成させるときのあなたの考慮に感謝します。私はそうではないことに留意してくださいECT、この本にはエラー、改訂、新しいエディションがあり、私の執筆で成功した経験を積むために、あなたの論理的な脳をできる限り考える必要があります。また、あなたが書くときに挑戦に直面しているときでさえ、私はあなたにとって良いことを意味することを理解してください。このように考えてみてください。コンピューターシステムをレンタルして、デジタルスペースで想像できることを実行し、遭遇するすべての情報を保存し、#$%!Yzeと整理し、それを理解するようになります。必然的に、あなたが摂取している情報や公開さえも困難に遭遇します。私は同じ困難に遭遇したので、私はあなたにこれを言います。この本をあなた自身の責任で使用し、コミュニティやコミュニティと協力して安全な設定内でソフトウェアを構築し、間違った方法で失敗したり成功したりしても個人的に物事を取り入れないでください。 、そしてなぜ私はあなたにこのテキストを持ってきて、あなたが狂気の道を分裂することなく成功するのを助けることができる理由Aves Meは、私たちが働くネットワーク、インターネットのパラレリスティックグローバルスケールのおかげで、誰もが世界規模で行っている通常の問題に遭遇している間、台無しにされ、破れ、擦り切れました。あなたは私がほんの少しの言葉を持っている人にあまり慣れていないかもしれませんが、私はあなたが読むことをお勧めします、あなたはあなたがあなたの仕事を完了するためにあなた自身のプロジェクトを構築しながら私を読み続けて理解し続けながら私を知るようになります。あなたの教授や教師があなたに割り当てられない限り、この本には宿題はありませんが、あなたが一緒に読んだときに自分でプロジェクトのポートフォリオを構築することを強くお勧めします。学んだことを適用してください。私のCapstoneプロジェクトは、以前のプロジェクトのコード、手作業で整然と書くことを学んだコード、そして私を助けた幅広いアイデアとヒントを学んだコードを組み込んでいるため、この本で読むもののほとんどの基礎です。簡単なアプリをスピンアップできるポイントに成功しますインターネットで、あなたに宣伝されている、またはニュースで、あなたの友人や家族を使用している人気のあるアプリのように、完全に機能し、外観と振る舞いをしています。 この本は何ですか: この本は、例ともチュートリアルです。ここでコード、コードの学習方法の手順、コードのデバッグとエラーの修正に関する情報、手順のトラブルシューティング、コードのバックアップと保存方法の手順、コードを破損した場合、コードを保護し、展開し、展開あなたのコードは、面白く、魅力的で、中毒性のあるインタラクティブなWebサイトを構築します。あなたが構築するソフトウェアは、あなたのウェブサイトの訪問者であるエンドユーザーにとって、可能な限り最も魅力的であるために絶対的な最善の光になります。この本では、プラットフォームとセキュリティとしてのWebに焦点を当てたソフトウェアデザインの多くの例を示します。基本を構築することにより、学習体験を開始しますバックアップとスクリプト機能を備えたUnixシェルを使用してOjectを使用します。次に、基本的なブログWebサイトを調べ、写真とビデオ機能をブログにアップグレードし、これらの機能を使用してフリーソフトウェアを使用してセキュリティソリューションを使用し、プラグ可能な認証モジュール(PAM)を使用してサーバーを保護します。次に、ファイルの処理と処理、ビデオ編集、音声寄付、バーコードスキャン、光学文字認識などの概念を確認します。途中で、無料で有料のオプションを使用して、ソフトウェアをより便利かつ安全にするのに役立つAPIを調べます。途中で、バレルとリピーターの設計、砲塔とドローンの設計、その他のプリンシパルなど、銃器や軍需品の設計と製造などの物理的なセキュリティや過激派のツールを探求します。自己防衛と弾力性を示します。ゲームを構築するために途中で休憩を取ります、2Dと3Dエンジンを終わらせ、基本​​的な寸法レンダリングソフトウェアとシリコンゴムでそれぞれ電子振動マッサージャー鋳造機のケーススタディの例で埋め込まれたハードウェアを使用します。途中で、ソフトウェアをよりよく保護するために、すでに利用可能な機械学習ソリューションも採用します。また、プロセスを合理化および保護するために、Webで利用可能なストックツールを使用します。この本は、Webアプリケーションを構築し、コンピューターおよび組み込み機械システムの専門的なネットワークと統合することに成功するためのガイドであり、全体的なソフトウェアと埋め込みハードウェアの構築ガイドと、背景知識や以前の経験のないガイドです。 この本はそうではありません: 本当にウェブサイトを持ちたい場合は、単純なストアをセットアップして必要なものを販売したり、ブログを投稿したり、写真やビデオを投稿したり、コードを1行に書いたりすることなく、その他のコードを書くことなく、単純なストアを販売するだけです。この本はそうではありません。この本は、より便利で完全にソフトウェアを構築する方法を教えてくれますまだプロトタイプである最新のソフトウェアを展開しているため、古い企業が運営するスケールで実行するのに費用がかかり、後方の複雑な企業にアピールしないため、既に見つけられるあらゆるソフトウェアよりも機能的で安全に機能しています。本当に何もしていない人のためにお金を稼ぎます。この本に密接に従うと、コードを書き、調査コードを作成し、独自のアプリを作成すると、自分がしていることからお金を稼ぐことができます。私はこの本から、人々が必要としたい情報が含まれており、私のアプリを購入または使用するときにすでに購入しているため、この本からお金を稼ぎます。この本はあなたのためのアプリを構築するものではありませんが、正しい方向に向けて、必要なツールと、Web用のソフトウェアの構築におけるあなた自身の成功を促進するスキルとヒントをあなたに武装させます。コードあなたは例として記述する必要があり、あなたとあなたのサポーター、ゲスト、顧客、ソフトウェアにまとめる準備ができています、riends、家族、訪問者、請負業者、およびインターネットの人々は、使用してサポートしたいと考えています。 あなたが学ぶこと: この本は、ソフトウェア、本当に機能的で有用なソフトウェア、メディア録音、顔認識などのセキュリティ機能、マシン読み取り可能なゾーンバーコードスキャン、Web APIのようなセキュリティ機能、ビデオと写真を認証、記録、レンダリングする方法、Bluetoothなどのメッセージの交換方法を教えてください。および近接フィールド(NFC)コミュニケーション。この本は、ネットワーク化されたコンピューターを使用する方法、Debian Linuxに焦点を当てた方法、Bashコードを構築する方法、ソフトウェアのインストールとバックアップをシームレスで自動化されたそよ風にする方法、ダイナミックメッセージ、スタイルを提供するためのバックエンドとしてPythonコードを構築する方法を教えてくださいブートストラップを使用してCSSスタイルを使用して、ネットワーク化されたデバイスを介してユーザーログインとインタラクティブ性を有効にし、インタラクティブなメディアや他のWebサイトとネットワークを構築して、検証用のテキストメッセージなどのセキュリティ機能を提供する目的、IDスキャン、画像およびビデオモデレーション、データソフトウェア、支払い処理、暗号通貨取引、非同期タスクなどを安全に保つためのラン作用。バッテリー、充電器、マイクロコントローラー、サーキット、モーター、センサーを使用して、はんだ、ワイヤー、3Dプリント、および鋳造材料を使用して、独自のBluetoothデバイスを構築する方法を学びます。添加剤の製造とツールとダイアキングに適用される3D設計プリンシパルを実証します。そのため、統合されたバッテリー、充電器、電子回路、機能出力を備えた独自の埋め込みハードウェアデバイスを製造できます。そして、それらをBluetoothとWebでネットワーク化します。具体的には、2つのケーススタディ、振動するマッサージャーと自家製の銃器を調べます。どちらも、グラフィカルインターフェイスまたはコマンドラインユーティリティとして利用できるOpenSCADでプログラムされ、より迅速な結果のためにWebに統合できます。 あなたは、以前の経験なしでゼロからウェブサイトを構築して展開する方法を学び、それを機能的で、安全で、美しく、最も便利にしますポータルに実用的です。機械学習とコンピュータービジョンを使用してサイトを安全で実用的なものにし、ウェブサイトからビデオとオーディオを記録し、音楽を寄付し、音楽を作り、有用なサンプルを作成し、ノイズを突破する方法を学びます。他のWebサイトを活用して、提供しなければならないすべての有用な情報を共有し、さらに重要なことに人々をソフトウェアやビジネスに連れて行くために、あなたがあなたのウェブサイトに直接リンクできるウェブサイトの最高のネットワークを構築することです。この本は、メディア、セキュリティ、機械学習に最も焦点を当てています。これは、適切なユーザーを引き付け、現実的で実用的な方法で間違ったソフトウェアを外すことで、Web向けのソフトウェアを構築するのに役立つ主要な3つのコンポーネントです。自動的で頑丈な間、実践と魅力的です。 この本は、UNIX、特にDebian(Ubuntu)、Bash Shell、Python、HTML、CSS、JavaScript、および多くの便利なソフトウェアパッケージを教えています。nリクエストのように、GitやFFMPEGなどの便利なBASHソフトウェア。また、暗号通貨を自動的に取引する方法を教え、暗号通貨や通常のデビットカードから支払いを行いながら、そうすることを選択した場合は、訪問者に収益のシェアを支払います。広告を通じてあなたのウェブサイトからお金を稼ぐ方法、検索エンジンのアプリを準備し、迅速にする方法を教えます。顧客があなたを見つけるために検索するものの最初のランキングにランク付けされ、多くの一般的なランキングでランク付けされます可能な限り検索します。ソフトウェアを販売したり、宣伝したり、サービスを探しているクライアントにアピールしたり、すでに存在し、安価でうまく機能する道を通してインターネット上で自分の名前を作る方法を教えます。私はあなたのために働くクラウドコンピューターにデータを保存し、あなたのデータを安く保存する方法、あなたのユーザーが望むこととあなたが望むことを行うウェブサイトを計画して構築する方法、そしてあなたのユーザーが従事させる方法を教えます通知、電子メール、テキストメッセージ、電話、その他の通路を使用して、電話でサイトをタップして、ユーザーを自由に使用できるようにして、ボタンをクリックするだけでユーザーを自由に戻します。この本は、メディアをテキストから写真、ビデオ、オーディオまで、メディアを大量に公開して配布することの実用性に焦点を当て、エンドユーザー(顧客)に良い印象を与え、作成するために自分自身を販売することに焦点を当てます。あなたとあなたのみを代表し、あなた、あなたのソフトウェア、あなたの会社を可能な限り最高の方法で見栄えを良くするウェブサイト、アプリ。また、コーディングのヒント、メイクアップや写真などの実用的な虚栄心、モデリングや演技など、私からいくつかのヒントとトリックを学びます。プラットフォームの健全なバランスをとる必要があるだけのコンテンツを配布しながら、あなたにEが必要以上に努力、仕事、またはお金のない実を結ぶ。 この本は、「実用的なWebベースの深い学習と例による例」と呼ばれています。理由は、特にWeb向け、特にセキュリティに焦点を当てて、実用的な観点からセキュリティに焦点を当てて、機能するコードの例を使用して、コードをコードすることを扱っています。テキストで概説されている実用的な目的。このテキストの学習コンポーネントには、機械学習、コンピュータービジョン、顔認識、画像とビデオのモデレーション、画像の強化、解像度の強化、画像キャプション、およびその他のタスクを処理するWebで実行する方法を紹介します。本物のコンピューターに伝達された画像、または光学コピー(画像の写真、または印刷された写真)としての画像の性質など、画像から供給された予測メトリック。機械学習は、Webセキュリティとソフトウェアセキュリティに関しては非常に重要です。これは、それ以外の場合は不可能なタスクをプリフォームすることができるためです。あなたのコンピューターパスコードでログインしますが、顔でログインする場合は、使用する方が安全かもしれません。サーバーコンピューターをこの安全なものにすることができます。通常、ユーザー名とパスコードを要求して、新しいログインまたは新しいIPアドレスの確認トークンを使用してログインしますが、大規模に構築している場合は、簡単です。基本的に安全で強力なソフトウェアを使用して、これで十分かもしれません。電子メールサービスやテキストメッセージサービスなど、他の人のソフトウェアに密接にソフトウェアを結び付けるだけで、ソフトウェアを安全にしたり、誰か(使用するサイト)を安全にしたりするには十分ではありません。 完璧に安全なソフトウェアを構築する人は誰でも、これが意味することのある程度の感覚を持っています。ソフトウェアは本質的に安全ではありません。なぜなら、アクセスに使用するデバイスとアカウントは、常に自由に自由に使えるとは限らず、ソフトウェアを意図していない人の手に渡る可能性があるため、ソフトウェア自体にリスクをもたらす可能性があるためです。これはこの本の焦点です。ネットワーク化されたコンピューターはデフォルトですWebサーバーは、サーバー自体で実行されている最先端のセキュリティツールを提供するため、長いキートークンとSSHまたはセキュアーシェルキーで固定されており、Webサーバーでセキュリティが最適です。 Webサーバーは、ユーザーがネットワークソフトウェアにアクセスできる場所であるため、ユーザーのデバイスの最も強力な部分であるユーザーのWebブラウザにアクセスできます。このツールキットは、テキスト、表示されているWebページをレンダリングでき、画像、オーディオ、ビデオ(顔や状態IDの写真など)を録画したり、Bluetoothラジオデバイスに読み書きしたり、近いフィールドに読み書きできることもできます。トランスポンダータグ、安価なキーカード、FOB、ステッカー、リング、さらには、Webサイトに結び付けられたWebサーバーによって生成および検証されたデータで読み書きできる一意のシリアル番号を備えたチップインプラント。自由に使えるすべてのツールを使用して、この本を使用して、安全なWebサイトを構築するための知識を身に付けます。あなたのために働き、あなたの入札を行い、見た目も感じたUREネットワーク化されたコンピューターシステム。 どこから始めるか: 特に、この本でコーディングの経験がある場合、またはこの本で詳細に説明する前述のツールのいずれかで、この本または任意のセクションで必要なコードを開始するセクションをスキップすることを歓迎します。同様に、ユースケースとその実用的な例を文書化します。コードを書く経験がない場合は、この本をすべて読むことを強くお勧めします。特に、この本があなたに合っていることを確認するために、前のセクションを読むことをお勧めします。この本があなたに合っていない場合は、Web開発自体について学ぶことに興味があるかもしれない友人や親relativeにそれを贈ることを検討し、それを借りて、私があなたを失敗させたギャップを埋めるために彼らから学ぶことを検討してください先生、または他の教師は私の前にしました。あなたがするところから始めて、あなたが便利なものを構築するつもりなら、この本のすべての部分が役立つでしょうpp、そして最高のアプリはエンドユーザーを念頭に置いて構築されていることを考えてください:顧客を知る。今、あなたは私を知っています、あなたはこの本を知っていて、あなたは始める準備ができています。まず、コンピューターをつかみます(ボックスストア、Amazon、または古いデスクトップが機能する最も安いラップトップでさえ、あなたのために機能する方法でセットアップします。 この本を読む方法: 強調表示されたテキストは、テキストがコマンドプロンプトに属し、実行するコードを書き込むことを示します。コマンドプロンプトは、キーボードに焦点を当てており、クリックをほとんどまたはまったく必要とせず、ワークフローをスピードアップし、物事を簡単にする必要があります。 はじめる: 飛び込みましょう。ローカルマシンにコードを作成することから始めて、インターネットに接続されたWebサイトを構築せずに開始します。これは、そもそも安全で、費用はかかりません。そしてあなたにとって簡単です。オペレーティングシステムに応じて、バッシュシェルに入ると少し違います。 Mac OSについては、この時点で仮想マシンをインストールすることをお勧めします。仮想マシン。 VirtualBoxやParalellなどのさまざまなプロバイダーは、仮想マシンを実行できますが、高速で合理化されたエクスペリエンスを作成するために推奨されるネイティブ環境を使用する場合は、マシンにUbuntuを直接インストールすることもできます。 LinuxまたはWindowsを使用している場合は、プロジェクトを作成するのは非常に簡単です。端末を開き、フィット感のあるサイズを調整し、ステップ2に従って開始します。Windowsを使用している場合は、ステップ1に従ってください。 ステップ1: - Windowsユーザーのみ Windowsでは、管理者とタイプとしてコマンドプロンプトを開きます WSL –Install ステップ2: - ここを続けるか、Windowsを使用していない場合はステップ1をここまでスキップします オープンターミナル(OSに応じて、WindowsのUbuntu、MacまたはLinuxのターミナル、または同様の名前と呼ばれます)は、プロジェクトを作成することから始めます。これは、ディレクトリを作成するMKDIRコマンドで行います。プロジェクトを保存するためにディレクトリを作成する必要がある場合は、推奨されます。ディレクトリに変更するCDコマンドと cd/path/to/directory-パスは、宛先ディレクトリの前にあるフォルダー(ファイル)です。デフォルトパスは〜または/home/username(ユーザー名がユーザー名)です。デフォルトのディレクトリに変更するには、CDまたはCDを入力してください〜 mkdirの例 - 「例」をディレクトリの名前に置き換えます これで、プロジェクトの作業ディレクトリがあります。別のマシンに切り替えたり、書いたコードを展開してWebの準備が整いたりする必要がある場合に備えて、このディレクトリを保存することが非常に重要であるため、次の数ステップでディレクトリをバックアップするスクリプトを作成します。しかし、スクリプトを構築するには少しコードが必要であり、コードはできるだけ便利になるために自動化する必要があります。スクリプトを作成して、最初にスクリプトを作成しましょう。スクリプトを作成して実行可能にすることから始めましょう。 sudo、chmod、touchを使用して、スクリプトに電話します


sudo touch /usr/bin/ascript
sudo chmod a+x /usr/bin/ascript
sudo nano /usr/bin/ascript
これで、スクリプトを作成し、実行可能にし、編集する準備ができています。 Nanoは、クリックせずにテキストを編集できるテキストエディターです。これは、グラフィカルユーザーインターフェイスを使用するよりもはるかに簡単です。 Nanoを使用してファイルを編集するには、Nanoを使用してからファイルへのパスを使用します。スクリプトを作成するスクリプトを作成すると、そもそもスクリプトを作成することにかなり似ています。上記と同じコードを使用して、スクリプトの名前、「アスクリプト」を引数パラメーター1ドルに置き換えます。これにより、単にSudo Ascript Newscriptを入力することでスクリプトを呼び出すことができます。この時点で、「Newscript」をスクリプトの名前に置き換えることで、新しいスクリプトを作成できます。 Nanoのコードは次のように見えます。

sudo touch /usr/bin/$1
sudo chmod a+x /usr/bin/$1
sudo nano /usr/bin/$1
また、ナノを閉じるために、コントロールキーを押し続けてXを押し、Yを押して、ファイルを保存していることを示し、リターンを押します。次に、これらの3つのコマンドを入力してスクリプトを編集する代わりに、Sudo ascript scriptを入力してスクリプトを再度編集することができます。これはうまくいきます!また、新しいスクリプトをシェルで呼び出すことで簡単に実行できます。今すぐ保存しましょう。バックアップスクリプトを作成して、新しいスクリプトを保存してから、バックアップスクリプトをバックアップしながら、プロジェクトディレクトリにバックアップしましょう。

sudo ascript backup
今、ナノで:

sudo cp /usr/bin/backup /path/to/directory/
sudo cp /usr/bin/ascript /path/to/directory/
ここで、/path/to/directoryは、mkdirで作成したプロジェクトへのパスです。後で、このような繰り返しのパスをループとリストでコピーする方法を学びます。このスクリプトを実行してコードをバックアップするには、コントロール+x、y、returnでファイルをNanoに保存し、以下をシェルに入力します

backup
この本を読んでシェルでフォローしているときにパスワードを求められている場合は、ユーザーパスワードを正しく入力してください。コマンドを再実行する必要がある前に3回トライします。上下矢印を使用してコマンドを再実行して編集できます。コマンドを右、左矢印、キーボードを削除して削除し、returnで実行する前に、コマンドを選択するために断続的に上下に押します。 おめでとう!ワーキングディレクトリに2つの重要なシェルスクリプトをバックアップする素晴らしいバックアップスクリプトを作成できました。プロジェクトが大きくなるにつれて、後で物事を動かしているかもしれませんが、これは今のところ機能します。クラウドのバックアップに進みましょう。これにはgithubを使用します(バックアップ用に他にも多数のgitソリューションがありますが、それらはすべて同じです。)gitは、編集をバックアップできるVerision Controlソフトウェアです。あなたがサーバーにそれらを作るときのソフトウェアまた、パスワードまたはキーの背後にあるソフトウェアのコピー全体をダウンロードすることもできます。ソフトウェアの保存には役立ちます。特に、コードの単一行が故障したときに時々破損する場合があるセキュリティでのLinuxインスタンスに移行するため、ロックアウトしている間は、バックアップの機会がない場合はコードがバックアップされない可能性があります。自動的にアップします。これをカバーします。 この時点でUbuntu仮想マシンをまだ使用していない場合は、この時点でUbuntu仮想マシンを使用して、作業Webサイトを構築してディープラーニングを実施するために必要なすべてのパッケージをインストールするときにライフを楽にすることをお勧めします。コンピューターの操作。近い将来、コードをWebサーバーに移動しますが、フィッシングに耐性のあるWebサーバーの背後に少なくとも数層のセキュリティがあることを確認し、多くのLinuxパッケージを使用するために使用したいと考えています。これ。それでもMac OSを使用したい場合は、検索してインストールできますeオンラインで必要なパッケージですが、この本やシリーズがカバーするすべてのパッケージに代わるものはない場合があります。 コマンドを実行して、バックアップスクリプトで作業をコミットするためにいくつかのコマンドを追加しましょう。

# …
git add –all
git commit -m “backup”
git push -u origin master
もう一度、Xを制御して保存します。 次に、このプロジェクトの時間構成を1回実行する必要があります。まもなくGITプロジェクトになるため、GITリポジトリから展開するたびにすべてのコマンドを入力する必要はありませんが、展開スクリプトを作成するときにこれを把握できます。まず、正しいディレクトリにいることを確認し、Gitリポジトリを初期化し、SSHキーを生成しましょう。

cd /path/to/directory
git init
git branch -m master
ssh-keygen
SSH-KeyGenを入力した後、.SSHというフォルダーの下のホームフォルダーに新しいキーを保存する必要があります。 id_rsa.pubと呼ばれます。このキーを見つけてコピーしましょう。それを見るために、

cd ~
cat .ssh/id_rsa.pub
SSHキーをアカウントに追加する前に、最後のコマンドによって返されるテキストをコピーし、Gitプロバイダー(理想的にはGitHub)でアカウントを作成します。アカウントを取得したら、右上のメニューをクリックして設定を入力してから、メニューのSSHキーとGPGキーのSSHキーを追加します。 SSHキーを追加し、貼り付けてタイトルを付けることでSSHキーを追加し、GitHubに保存して戻って新しいリポジトリを作成します。これは他のGITプロバイダーでも同様です。ドキュメントを読む必要があります。新しいリポジトリ構成で、リポジトリに説明名を付け、公開するかどうかを決定し、まだ包含用のファイルを構成しないようにしてください。リポジトリが作成されたら、クローンをSSH URLでコピーし、次のコマンドに貼り付けます。

git remote add git://… (your remote URL)
これで、CDを使用してリポジトリに戻ることができます。これに精通しています。バックアップで今すぐバックアップスクリプトを試してください 素晴らしい!今、私たちは本当にコーディングを得ることができます。 BashとGitをよく把握できるようになったので、Djangoをインストールしましょう。 Djangoはソフトウェアを自動的にバックアップできるようにします。Bashはこれを行うこともできますが、Djangoはより安全な実装をする必要があります(無効にしてより簡単に構成できます)。 Ubuntuにソフトウェアをインストールするには、Sudo Apt-Getコマンドを使用します。まず、すでに持っていたソフトウェアを更新してアップグレードしましょう。これは、sudo apt-getアップデートとsudo apt-getアップグレード-yで実行できます。次に、次のコマンドを使用して、PythonとVirtual EnvironmentのホームであるVirtual Environmentをインストールしましょう。sudoapt-getインストールpython-is-python3 python3-venv これは、Ubuntuインスタンスのソフトウェアインストールに関してDjangoを使用するために必要なすべてです。 WindowsとLinuxの場合、これはかなり簡単なはずですが、Macの場合は仮想マシンをインストールしてください。ubuntu環境をセットアップするために、VirtualboxやParalellsデスクトップなどの無料またはParalellsのデスクトップなどの無料または有料の仮想環境を使用してLinuxを使用します。この場合、UbuntuはWebサイトが実行するソフトウェアであり、前述のすべてのソフトウェアでWebサイトをホストできるため、この場合は重要です。 Djangoを掘り下げましょう。 私たちのディレクトリで再び、

python -m venv venv # コードが保存されている仮想環境を作成します
source venv/bin/activate # 仮想環境をアクティブにします
pip install Django
django-admin startproject mysite . # ここで、MySiteは現在のディレクトリから始めています。
DjangoはWebサーバーをホストしており、基本的なローカルWebサイトを稼働させるために必要なすべてを行っているため、Djangoが始めたばかりです。 Djangoがインストールされたので、設定を少し編集して、必要な方法を機能させるようにしましょう。まず、新しいアプリを作成しましょう

python manage.py startapp feed
最初のアプリはフィードと呼ばれていることに気付くでしょう。アプリは好きなものを何でも呼び出す必要があり、新しいアプリを作成しますが、各アプリの名前は、アプリがコードで参照されるたびに一貫している必要があります。新しいアプリを追加するには、常にStartProjectに名前が付けられたアプリが作成した他のディレクトリのsettings.pyを常に編集します。ナノを使用して、

nano app/settings.py
設定で、installed_appsを見つけて、[]を3行に分離します。空の中心線に4つのスペースを使用して、「フィード」またはアプリの名前を追加します。 settings.pyのこのセクションは次のようになります。

INSTALLED_APPS = [
    'feed',
]
忘れる前に、Djangoが機能していることをテストしましょう。コマンドPython manage.py runserver 0.0.0.0:8000を使用して、サーバーを実行してから、コードを実行しているコンピューター上のWebブラウザでhttp:// localhost:8000に移動して、Webページのサンプルを参照してください(動作!)他のコマンドと同じコントロールcでサーバーを終了します。 それでは、いくつかのPythonコードの作成に掘り下げましょう。 Djangoには3つの主要なコンポーネントがあり、それらはすべてコードで完全に実行されています。コンポーネントはモデル、ビュー、およびテンプレートと呼ばれ、それぞれがユーザーに配信される前にそれぞれより高いレベルと低レベルにあります。 このモデルは、取得、並べ替え、レンダリングのためにデータベースに情報を保存するコードです。 ビューは、モデルのレンダリング、操作、および変更された方法を決定します。ほぼすべてのビューがモデルを直接使用します。 テンプレートは、テンプレート言語と呼ばれるいくつかの余分なベルとホイッスルを備えたHTMLコードです。テンプレートは、Pythonコードで満たされているビューによってレンダリングされます。ビューからモデルや情報(usuall文字列や整数)などのコンテキスト。 Djangoには、以下を含むがこれらに限定されない他のコンポーネントもあります。 説明したようにアプリを構成する設定。 URLは、Webアプリケーションの特定の部分にアクセスするためにユーザーが従うパターンです。 サーバーに送信される情報が処理され、データベースとユーザーにレンダリングされる方法を定義するフォーム。これらは、サーバー側の情報を処理する基盤であり、コンピューターが保存しているあらゆる種類の情報、特にテキスト文字列、数字、真の/誤ったブール人(通常はチェックボックス)を受け入れることができます。 HTMLコードとテンプレート言語であり、PythonとHTMLのギャップを埋めるテンプレートは、Python情報をWebにアクセスできるようにしながら、誰でもアクセスできるHTMLコードとして提供できるHTMLコードとして提供できます。そうでないリモートデバイスのさまざまな目的のためにサーバーの近くにいるためにEED。 通常、JavaScriptであり、サーバーが提供し、テンプレートにリンクしているライブラリである静的ファイル。 サーバーがサービスを提供している、外部的にホストされている、またはホスティングのために別のサーバー(バケット)に投稿される前にサーバーに書き込まれるメディアファイル。 ミドルウェアは、すべてのビューと同時に実行され、ビューに「含まれている」と見なされるコードの部分です。 コンテキストプロセッサは、各ビューのコンテキストを処理し、追加のコンテキストを追加するために使用されます。 ビューがレンダリングされる前に、ユーザーまたはリクエストが特定の要件に合格することを検証するテスト。 消費者は、WebSocketsがコミュニケーションにどのように処理し、応答するかを指示します。 adminは、モデルを登録するために使用され、Django管理ページ内で詳細に操作できるようにします。ここでは、グラフィカルインターフェイスを介してデータベースを管理できます。 非同期タスクを定義するセロリは、djangoコードの一部を開始できますすぐに次のタスクまたはコード行に進む前に。 Djangoは他の多くのコンポーネントを持つことができます。これについては、ここで詳しく説明します。 Djangoをより機能的にする方法はたくさんあります。これは、非同期タスクを実行する高速で合理化された通信チャネル、セロリ、特にDjangoを拡張するための他の多くのソフトウェア、特にビュー機能で他の多数のソフトウェアであるWebSocketを追加します。コードが実行されます。ビュー関数は、通常、特定のURLパターンまたはサーバーのセクションに固有のすべてのコードを宣言するため、重要です。 まず、ビュー関数を調べてみましょう。ビュー関数は、ビューで使用されるコードを示すインポートから始まり、通常の関数の定義またはクラスを使用して定義されます。最も単純なビューは、関数定義defで定義され、基本的なテンプレートでHTTPResponseを返します。 「Hello World」というテキストを返すために基本的なビューを定義することから始めましょう。追加するたびに覚えておいてくださいfter def、for、forなどのようなステートメントをfterするには、機能に適用したい事前の定義ごとに4つのスペースを追加する必要があります。これらのそれぞれがすぐに意味することに取り組みます。 当社のサイトのディレクトリから、NANOを使用してFeed/Views.pyファイルを編集し、次の行を最後に追加します

from django.http import HttpResponse

def hello(request):
    return HttpResponse('hello world')
DjangoのHttpresponseは、開閉で示されるテキスト文字列で応答します。リクエストや文字列など、情報やクラスに情報を渡すたびに、括弧(、開閉)を使用する必要があります。 これがまだ私たちの見解を見る必要があるすべてではありません。もちろん、ビューが正確にある場所にサーバーに伝えていませんが、ビューをレンダリングするパスを定義する必要があります。 App/urls.pyで基本的なパスを定義することから始めましょう。後でパスグループに入ります。 App/urls.pyで、作成したばかりのビューをインポートし始めた後、インポートステートメントの後に行を追加します。

from feed import views as feed_views
それでは、ビューパターンを定義しましょう。ビューパターンには、サーバー内にビューが存在するサーバー(ユーザーがナビゲーションバーに入力してWebページに入力するURLパス)、ビューコンポーネントが指定されている場所にある3つのコンポーネント、パスコンポーネントの3つのコンポーネントがあります。ビューのフレンドリーな名前で、テンプレートを使用するときにパターンを簡単に取得できます。特に、必要に応じて別のビュー用のスペースを作成したり、より論理的な名前を取ったりするために、名前を変更および更新できます。あなたのコードベースは、価値があり、作業しやすくするために柔軟性と即興を必要とする絶えず変化する環境になるため、このように物事を行い、柔軟性を持つことは理にかなっています。あなたの見解がどのように見えるかは次のとおりです。これをurlpatterns = [app/urls.pyのセクションに追加できます。ビューパターンは、上記の3つのコンポーネントとパスと呼ばれる関数で定義されます。あなたのURLパターンはリストですので、必ずそれらの各アイテムを終了してくださいコンマで、これはそれぞれを分離するためです。また、各アイテムは、設定のアプリと同じように、その前に4つのスペースを備えた新しいラインに移動する必要があります。 Webサーバーのルートディレクトリで実行されるビューを作成するために、Viewの最初のコンポーネントを空の文字列関数で定義します。あなたのurls.pyは今のように見えるはずです

from feed import views as feed_views

urlpatterns = [
    path('', feed_views.hello, name='hello'),
]
これは、完全に静的なDjangoを使用してWebサイトを作成するための基礎です。画像、ビデオ、オーディオなどのキャッシュ情報を開始できる、よりダイナミックなWebサイトを作成するには、次に探索するモデ​​ルを使用する必要があります。とりあえず、コードを確認してサーバーを実行しましょう。エラーをコードに確認するには、実行してください。

python manage.py check
エラーメッセージがある場合は、アプリに行った変更を慎重に確認し、外部または不足しているスペース、余分なキャラクター、閉じられていない文字列、タイプミス、誤って修正する必要があるものがあるかどうかを確認する必要があります削除された文字など。エラーメッセージを読んで(ある場合)、作成または編集したファイルへのパスを行番号とともに確認できるはずです。そのファイルと行を調べて、そこにあるものを修正できるかどうかを確認してください。問題を修正した場合は、上記のコマンドをもう一度実行します。ソフトウェアが実行され、動作している場合、出力「システムチェックは問題を特定しなかった」が表示されます。今、あなたは行く準備ができています。サーバーを実行します:

python manage.py runserver 0.0.0.0:8000
Webブラウザーを開き、http:// localhost:8000に移動します。括弧内にテキストが返され、httpresponse関数の引用が表示されているのを見る必要があります。これは基本的な例にすぎませんが、ここまで行えば、Linux、Bash、Python、およびDjangoがどのように機能するかの基本を理解しています。いくつかのデータベースモデリングをより深く掘り下げ、情報を保存する際のPythonクラスのパワーを探りましょう。次に、JavaScriptと機械学習を使用して、サイトを完全に紹介し、柔軟で安全にする前に、HTMLとCSSのグリップを取得し始めます。 クラスは、アプリのモデルに保存されます。 nanoを使用して、app/models.pyを編集し、新しいクラスを追加します。クラスはクラス定義で定義され、この場合はモデルから継承するスーパークラスに渡されます。モデル。クラスの名前は、クラスの定義の後に行われ、クラスに関連する属性と関数の定義が以下に示される前に、クラスの定義a :(コロン)が使用されます。私たちのクラスそれを取得して一意に保つために使用できるIDが必要です。また、情報を保存するためにテキストフィールドも必要です。後で、タイムスタンプ、ファイル、ブリアンを追加できます(コードがモデルをどうするかについての決定を下すのに役立ち、それを並べ替えるために使用できる)を追加できます。サーバーなどに。コードを開梱しましょう

from django.db import models # クラスを定義するために使用されるインポートとそれは属性です

class Post(models.Model): # クラス自体の定義
    id = models.AutoField(primary_key=True) # モデルのIDは、モデルをクエリし、一意に保ち、作成したらモデルと対話する必要がある場合に役立つ自動化されたキーです。
    text = models.TextField(default='') # クラスストア、この場合、いくつかのテキストが空の文字列にデフォルトである属性。
前に行ったように、ファイルを閉じて保存します。 このクラスを更新する際にアプリが進化するときに調査する他の多くのフィールドとオプションがありますが、これはテキストを投稿するアプリを作成するための基本的な必需品です。ただし、このモデルは単独では機能しません。前述のように、このモデルを機能させるにはカスタムビューとカスタムURLパターンが必要になります。また、テンプレートとともにフォームも必要です。最初にフォームを調べてみましょう。 フォームを定義するには、nanoでapp/forms.pyを編集し、次の行を追加します。フォームクラスの2つのインポート、作成したモデル(Feed.models.post)、モデルと同様のクラス定義、およびフォームが相互作用するモデルを定義するMetaと呼ばれるサブクラスとともにフィールドが必要です。と。フォームには、リクエスト、モデル、またはその他の情報に基づいて設定する初期化関数を持つこともできます。これを後で検討します。 モデルフォームは、モデルを作成したり、モデルを編集したりできるため、非常に便利です。そのため、両方に使用します。 forms.pyで1つを定義しましょう

from django import forms
from feed.models import Post

class PostForm(forms.ModelForm):
    text = forms.CharField(widget=forms.Textarea)
    class Meta:
        model = Post
        fields = ('text',)
これは、フォームとモデルがどのように見えるかの基本です。このモデルフォームを使用して、投稿をインスタンス化または編集して、含むテキストを変更できます。次に、このフォームをビューに統合することを検討します。まず、移行を行い、データベースを移行して、モデルが実行されたときにモデルと対話できるようにしましょう。これを行うには、次のコマンドを実行します。

python manage.py makemigrations
python manage.py migrate
これには実行に時間がかかりますが、一度実行すると、ビュー、ミドルウェア、またはソフトウェアの他の場所でモデルにアクセスできます。私たちのモデルを見ることができるビューを作成して続けましょう。記載されているように、Feed/Views.pyを編集し、次のコードを追加します。 #signの後に何も追加する必要はありません。そのコードは、コードに関する情報を示すために使用されるコメントです。まず、モデルをビューでインポートし、ディスプレイのリストとしてテンプレートでレンダリングできるコンテキストに追加することから始めます。次に、フォームとモデルをボタンでレンダリングできるテンプレートを追加して、モデルに基づいて新しいオブジェクトを作成してサーバーに投稿できます。これは複雑に聞こえるので、一歩一歩見しましょう。ビューを完了する前に、モデルをレンダリングするだけのテンプレートを作成し、シェルに新しい投稿を作成して確認できることを確認しましょう。その見方は次のとおりです。

from feed.models import Post
from django.shortcuts import render, redirect
from django.urls import reverse

def feed(request):
    posts = Post.objects.all() # これまでのところ、データベース内のすべての投稿をクエリします
    return render(request, 'feed/feed.html', {
        'posts': posts,
    })
これはすべて、私たちが一番下に到達するまで非常にシンプルに見えます。レンダリング、前の例のようなHTTP応答ではなく関数によって返される値は、常に最初の入力として要求を受け取り、コンテキスト(この場合はデータベースの投稿)を受け入れます。これはテンプレートでレンダリングできます。 、および関数で定義されたテンプレートを返します。このテンプレートは、Jinja2と呼ばれる言語の少しのHTMLドキュメントになり、Python情報をHTMLにレンダリングします。 テンプレートの作成を開始するには、フィードに2つのディレクトリを作成します。

mkdir feed/templates
mkdir feed/templates/feed
次に、上記のディレクトリでテンプレートを編集し、フィード/テンプレート/フィードを編集し、この例のコードを追加します。この例のテンプレートを見てみましょう。
 
<!doctype HTML>
<html>
<body>
<legend>Feed</legend>
<hr>
{% for post in posts %}
<p>{{ post.text }}</p>
{% endfor %}
</body>
</html>
 
これは非常にシンプルなテンプレートです。 HTMLタグの開閉、ドキュメントタイプのタグ、レジェンドタイトル付きのボディタグ、画面全体に小さな行を追加するブレークタグ、および投稿のリストの各投稿を段落としてレンダリングするループ用のループを定義します。テンプレート。これは投稿をレンダリングするのに必要なすべてですが、データベースにはまだ何もありません。シェルでいくつかを作成しましょう。 manage.pyでシェルを実行できます

python manage.py shell
次に、ポストモデルをインポートしましょう

from feed.models import Post
次に、文字列を使用した簡単な投稿を作成し、シェルを終了します。文字列は、有効なテキストである限り、何でもすることができます。

Post.objects.create(text='hello world')
exit()
最後に、フィードにURLパターンを追加する必要があります。フィードアプリは複数のURLを使用し、ファイルサイズを小さく保ちたいので、このようなフィードアプリでローカルURLS.PYを作成しましょう。

from django.urls import path
from . import views

urlpatterns = [
    path('', views.feed, name='feed'),
]
また、ベースアプリでurls.pyを編集する必要があります。これが何であれ、これが最初に作成したディレクトリでした。 app/app.pyを編集し、URLパターンに次のことを追加します

from django.urls import include # 上に

urlpatterns = [
    # ...ここでの以前のコード
    path('feed/', include(('feed.urls'), namespace='feed')),
]
これで、Python Manage.py runserverでサーバーを実行すると、データベース内のアイテムとともにモデル、ビュー、テンプレート、およびURLパターンがあるため、作成したページが表示されます。次に、作成したフォームを実装し、独自の投稿の作成を開始しましょう。しかし、あまりにも多くのコードを書く前に、以前に書いたスクリプトを使用してバックアップを作成しましょう、バックアップ。このスクリプトをシェルで実行し、少し待ってください。すべてのコードがGITリポジトリにバックアップされます。

backup
フォームの実装は比較的簡単です。フォームをインポートし、[[ポスト]リクエストハンドラーをビューに追加し、データベースに投稿を保存してから、同じビューにリダイレクトします。既にインポートしたリダイレクト関数と、ViewパターンのURLを取得するためにReverseと呼ばれる別の関数を使用できます。含まれているパターンの名前空間がフィードであり、ビューはフィードとも呼ばれるため、文字列「フィード:フィード」でこれを照会します。

from feed.forms import PostForm

def feed(request):
    posts = Post.objects.all() # これまでのところ、データベース内のすべての投稿をクエリします
    if request.method == 'POST': # POSTリクエストを処理します
        form = PostForm(request.POST) # フォームのインスタンスを作成し、データを保存します
        if form.is_valid(): # フォームを検証します
            form.save() # 新しいオブジェクトを保存します
        return redirect(reverse('feed:feed')) # GETリクエストで同じURLにリダイレクトします
    return render(request, 'feed/feed.html', {
        'form': PostForm(), # レンダリングできるように、フォームをコンテキストに渡すようにしてください。
        'posts': posts,
    })
次に、新しいフォームを考慮してテンプレートを更新する必要があります。これを使用してこれを行うことができます
HTMLにタグを付け、送信ボタンを使用してHTMLテンプレートのフォームをレンダリングします。また、最初にページをロードせずに外部サイトがフォームに投稿するのを防ぐトークンであるCSRFトークンも必要です。
 
<!doctype HTML>
<html>
<body>
<legend>Feed</legend>
<form method=”POST”>
{% csrf_token %}
{{ form }}
<button type=”submit”>New Post</button>
</form>
<hr>
{% for post in posts %}
<p>{{ post.text }}</p>
{% endfor %}
</body>
</html>
 
これを分解しましょう。新しいフォームクラス、トークン、フォーム自体、および送信ボタンがあります。非常にシンプルですが、それを見てみると、見た目を良くしたいと思うかもしれません。機能し、フォームで新しい投稿を投稿でき、データベースに保存されます。ここでいくつかのことが起こっています。 HTMLタグを使用して、ドキュメントがHTMLドキュメントであることを宣言し、テンプレートタグ({%…%})を使用して、フォームにトークンをレンダリングし、別の{{…}}をレンダリングします。また、ブロックタグとテンプレートタグを使用してテキストをレンダリングするループもあります。ブロックタグは、テンプレートのセクションがどのようにレンダリングされるかを定義できるため、非常に重要です。テンプレートタグは、変数をコードに入力する方法の基礎です。 これで、アプリの見た目を良くする必要があります。今のところは本当に基本的に見えるからです。これを行うには、インライン、またはドキュメント内の各オブジェクトに結び付けられたクラスのいずれかを使用することで行うことができます。 CSSはページ上のすべてのものをどのように見えるかを伝えているので、本当にいいです、そして、それを本当によく見せることができます。これを行うことができるいくつかのライブラリがありますが、私の個人的な行くことはブートストラップです。 ブートストラップは彼らのウェブサイトからダウンロードできます、getBootStrap.com/。そこに着いたら、ボタンを押してインストールドキュメントを読み取り、cdnセクションを介してincludeからコードをコピーします。 HTMLドキュメントの上部にあるこのコードが、Headと呼ばれるタグが必要です。また、各テンプレートでこれらのリンクを再現する必要がないように、先に進んでベーステンプレートを作成しましょう。 MKDIRテンプレートを使用したテンプレートと呼ばれる新しいディレクトリを作成し、テンプレート/base.htmlを編集します。 このように見えるはずです:
 
<!doctype HTML>
<html>
<head>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>
 
CSSとJavaScript、.CSSおよび.JSファイルをコピーしてください。将来、サイトをより機能的にするためにJavaScriptが必要になるためです。 それでは、Bash Shellに戻り、クイックコマンドを実行しましょう。仮想環境にアクセスする必要がある場合は、Source venv/bin/activateを入力する必要があることを忘れないでください。これにより、DjangoがアクセスできるようにPythonパッケージをローカルにインストールできます。 Django Bootstrapクラスによって生成されたフォームを提供するために、Crispy FormsというPythonパッケージを使用します。これを次のコマンドでダウンロードできます

pip install django-crispy-forms
これがインストールされたら、settings.pyに追加します

INSTALLED_APPS = [
    # …以前のコードはここにあります
    'crispy_forms',
]
さて、フィードテンプレートに戻って、いくつかのものを削除できます。ドキュメントの開始と終了を削除し、拡張機能とブロック定義を使用して、ベーステンプレートからの継承に置き換えましょう。また、フォームにテンプレートフィルターインポートとテンプレートフィルターを追加し、テンプレートフィルターを追加します。最後に、フォームのボタンにブートストラップクラスを追加して、ボタンのように見せましょう。それは次のようになります:
 
{% extends 'base.html' %}
{% block body %}
{% load crispy_forms_tags %}
<form method=”POST”>
{% csrf_token %}
{{ form|crispy }}
<button type=”submit” class=”btn btn-outline-primary”>New Post</button>
</form>
<hr>
{% for post in posts %}
<p>{{ post.text }}</p>
{% endfor %}
{% endblock %}
 
美しい!それはすでにかなりのコードです。次に、それをテストし、すべてが見栄えが良いことを確認し、すべてが適切に機能していることを確認する必要があります。以前の指示に従ってサーバーを実行し、サイトが大丈夫になっていることを確認してください。素晴らしい仕事!次のステップに進む準備ができており、同様のURL、フォーム、ビュー、テンプレートを使用してユーザーログイン機能を追加します。ベーステンプレートは重要であり、必要に応じて変更を加えて変更を加え続けますが、ユーザーがユーザー名とパスコードでログインできるようにし、最終的にはさらに重要な情報を使用できるようにすることで、サイトをより安全にすることに焦点を当てましょう。アプリを安全に保つのに役立ち、自分のアカウントにのみアクセスできます。 これを行うには、Djangoに組み込まれたユーザーモデルを使用する必要があります。ユーザーモデルは、私たちの投稿のようなデータベースモデルであり、ユーザーをWebサイトにログインするようにレンダリングできます。将来的には、サイトをインターネットに展開する前に、このモデルを他のモデルに起因するモデルを拡張し、フィッシングに耐性のあるログインのための追加のセキュリティ対策を構築します。まず、Djangoが提供するいくつかの組み込みのログインフォームを使用します。まず、基本ログインページのテンプレートとビューをレンダリングするために使用する新しいアプリを作成しましょう。また、ピンコード、顔認識、近いフィールド通信、外部デバイス、マルチファクター認証、指紋認識など、アプリを保護するために、継続的なログインチャレンジを表す他のアプリを作成します。 私たちはすでにアプリの開始について話しました。私たちのディレクトリから、仮想環境の内部で、pass.pyこれらを

python manage.py startapp users
これで、新しいアプリのディレクトリが必要です。ユーザーログインに対応するディレクトリにビューを作成することから始めましょう。 Djangoはユーザーログインのビューを構築していますが、カスタムビューが必要であるため、これらは適切ではありません。 このビューでは、POSTリクエストをチェックし、Djangoからインポートされたログインフォームへのパスリクエストを確認し、ユーザーアカウントを認証し、ユーザーをログインしてからフィードアプリにリダイレクトします。 ユーザー/views.pyで、次のコードを追加します

from django.shortcuts import render, redirect
from django.urls import reverse
from django.contrib.auth.forms import AuthenticationForm, SetPasswordForm
from django.contrib.auth import authenticate, logout
from django.contrib.auth import login as auth_login
from django.contrib import messages

def login(request):
    if request.method == “POST”:
        username = request.POST['username'] # 投稿リクエストからユーザー名とパスワードを取得します
        password = request.POST['password'] # ユーザーを認証します
        user = authenticate(username=username, password=password)
        if user:
            auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend')
            messages.success(request, 'Your password was accepted. Please continue')
            return redirect(reverse('feed:feed'))
        else: messages.warning(request, 'Username or password incorrect. Please try again')
    return render(request, 'users/login.html', {'form': AuthenticationForm()})
これは、基本的なログインビューに必要なすべてです。それでは、ベーステンプレートを拡張して、ビュー用のフォームを作成しましょう。まず、ユーザーフォルダーにテンプレート用の新しいディレクトリを作成します。

mkdir users/templates
mkdir users/templates/users
これで、ユーザー/テンプレート/ユーザー/login.htmlを編集できるはずです。私たちがそれに取り組んでいる間、ユーザーがサインアップできるようにするテンプレートを作成します。

nano users/templates/users/login.html
さて、テンプレートで、
 
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<form method="POST">
    {% csrf_token %}
    <fieldset class="form-group">
        <legend class="border-bottom mb-4 break">Log In</legend>
        {{ form|crispy }}
    </fieldset>
    <div class="form-group">
        <button class="btn btn-outline-info" type="submit">Login</button>
    </div>
</form>
{% endblock %}
 
これがログインテンプレートの基本です。構造の他のテンプレートと同じですが、レンダリングされると少し違って見えます。このコードをコピーして、register.htmlという別の非常に類似したテンプレートを構築します。ここでは、文言を変更し、ビルドする新しいフォームを使用します。最初にテンプレートを作りましょう。ユーザー/テンプレート/ユーザー/register.htmlを編集し、次のコードを追加します。
 
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<form method="POST">
    {% csrf_token %}
    <fieldset class="form-group">
        <legend class="border-bottom mb-4 break">Create an account</legend>
        {{ form|crispy }}
    </fieldset>
    <div class="form-group">
        <button class="btn btn-outline-info" type="submit">Register</button>
    </div>
</form>
{% endblock %}
 
次に、ユーザー登録用のフォームを作成し、モデルでユーザーログインをアップグレードする前にビューに戻りましょう。このフォームは、最初から基本的になりますが、将来的には契約やCaptchaなどの詳細とセキュリティ機能を組み込みます。 nano users/forms.pyでフォームを編集し、次のコードを追加します。

from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm

class UserRegisterForm(UserCreationForm):
    email = forms.EmailField()

    class Meta:
        model = User
        fields = ['username', 'email', 'password1', 'password2']
ここには別のフォームがありますが、これはかなり単純に機能します。これは、ユーザー名、電子メール、パスワードを備えたユーザーレジスタフォーム、およびパスワードの確認フィールドです。このフォームは通常のforms.formクラスを拡張していないことに注意してください。これは、メタがあることを意味するモデルフォームです。 1つのフィールドは同じように定義され、クラスメタはモデルを定義します。フォームはフォームに書き込まれる残りの情報に対応します。これのほとんどは、すでにDjangoの組み込みのユーザーCreationFormに存在しているため、クラスの基礎としてそれを使用します(括弧内に渡されます)。 次に、フォームとテンプレートができたので、ユーザーを登録するビューを調べます。これは、新しい投稿ビューのようなモデルフォームです。ユーザー/views.pyを編集し、次のコードを追加します。

# …輸入
from .forms import UserRegisterForm

def register(request):
    if request.method == “POST”:
        form = UserRegisterForm(request.POST)
        if form.is_valid():
            user = form.save()
            messages.success(request, 'Welcome to the app, {}.'.format(user.username))
    return render(request, 'users/register.html', {'form': UserRegisterForm})
これは、ユーザーを登録するために必要なすべてですが、より多くの情報が必要です。ユーザーが登録した時間、サイトで最後になった時間、伝記、タイムゾーンなどの情報についての情報も知りたいです。また、ユーザーを考慮してフィードモデルの投稿を更新する必要があります。各ユーザーへのモデルと属性の投稿。それを行うために、両方のアプリでModels.pyを更新します。フィードモデルを編集することから始めましょう。今はこのように見えるはずです:

from django.db import models # …金額
from django.contrib.auth.models import User

class Post(models.Model):
    id = models.AutoField(primary_key=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, related_name='posts') # この行を追加します
    text = models.TextField(default='')
ファイルに追加された2行目に注意してください。これは外部キーであり、各投稿を投稿ごとに1人のユーザーに帰属させるため、ユーザーごとに投稿を保存し、ユーザーに起因することなく投稿を作成できないことを確認できます。この外部キーを表すクラスで定義します。これは、必要に応じてユーザーを削除できることを確認するために、ユーザー、nullおよび空白の引数で投稿が削除されるようにするための削除引数を定義し、すでに投稿にユーザーが不足していることに対応できるようにします。作成された関連名。ユーザーが作成するポストオブジェクトを参照するために使用できます。この関連名は、投稿の著者であるPost.authorとは異なり、投稿自体を投稿したユーザーに提供されます。これで、urning user.posts.all()、またはauthor.posts.all()を実行してユーザーが作成した投稿を取得できます。 それでは、ログインをより回復力のあるものにしましょう。私たちは、ログインを許可する回数を制限するだけで、フィッシングに対してサイトの脆弱性をはるかに脆弱にすることができます。サイト、これは非常に簡単です。また、アプリの開発を続けている間、各ユーザーに関する情報を保存し始めましょう。ユーザー/models.pyを編集して、以下を追加します

from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True, related_name='profile')
    account_created = models.DateTimeField(default=timezone.now)
    last_seen = models.DateTimeField(default=timezone.now)
    can_login = models.DateTimeField(default=timezone.now)
    preferred_name = models.CharField(max_length=20,default='', null=True, blank=True)
    bio = models.TextField(blank=True, default='')
このモデルはPOSTモデルとかなり似ていることに注意してください。 DateTimeフィールドにデフォルトを設定できる追加のインポートTimeZoneがあり、投稿のようなCarchersFieldとTextfieldもあります。これらすべてのタイムスタンプを使用すると、サイトを確保し、その使用を理解することができ、テキストフィールドにより、各ユーザーまたは著者に関する情報をWebサイトでレンダリングすることができます。 OnetOonefieldは唯一のマイナーな考慮事項である必要があります。これは、ForeginKeyとまったく同じ動作をしますが、後続のモデルごとに1つしか動作しません。これにより、ユーザーは1つのプロファイルしか持っていませんが、多くの投稿がある場合があります。 次に、プロファイルを考慮してログインと登録ビューを改善しましょう。まず、ユーザー/Views.pyを編集し、レジスタビューに焦点を当てます。

# …金額
from .forms import UserRegisterForm

def register(request):
    if request.method == “POST”:
        form = UserRegisterForm(request.POST)
        if form.is_valid():
            user = form.save()
            Profile.objects.create(user=user) # この行を追加して、ユーザーのプロファイルを作成してください
            messages.success(request, 'Welcome to the app, {}.'.format(user.username))
    return render(request, 'users/register.html', {'form': UserRegisterForm})
これにより、情報を入力することなく、ユーザーのプロファイルが作成されます。これで、ユーザーアカウントをあまり頻繁にログインできないことを確認するか、少なくともパスワードを頻繁に試すことができないことを確認する必要があるため、ログインビューを更新します。

# …金額
from .models import Profile
from django.utils import timezone
import datetime

def login(request):
    if request.method == “POST”:
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(username=username, password=password)
        if user and user.profile.can_login < timezone.now(): # ユーザーがログインできるかどうかを確認することに注意してください
            auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend')
            messages.success(request, 'Your password was accepted. Please continue.')
            return redirect(reverse('feed:feed'))
        else: # ログインが成功しなかった場合、
            messages.warning(request, 'Username or password incorrect. Please try again.')
            user = User.objects.filter(username=username).first() # これはユーザープロファイルを更新する部分です
            if user: 
                profile = user.profile
                profile.can_login = timezone.now() + datetime.timedelta(seconds=15) # だから彼らは数秒間再びログインすることはできません
                profile.save()
    return render(request, 'users/login.html', {'form': AuthenticationForm()})
これは、セキュリティの基本的な基本です。サイトが、可能なあらゆるパスワードの組み合わせを試したり、同時にいくつかのパスワードの組み合わせを試してみても、サイトが脆弱ではないことを確認してください。これは、パスコードを知っており、いくつかのデバイスにログインする普通のユーザーにとってイライラすることはありませんが、アプリから多数のフィッシングロボットを締め出します。変数Can_Loginを使用したIFステートメントを追加し、過去の時間であるはずであり、同じユーザー名を使用してログインが失敗したごとに更新する必要があることに注意してください。これにより、悪意のあるユーザーは、それほど迅速にパスワードを推測することができません。 datetime.timedelta()の秒数も更新でき、ウェブサイトはより弾力性が高いが、より多くの秒でわずかに使用できるようになります。最初に15をお勧めします。 覚えておいてください、私たちは仕事を保存するためにバックアップスクリプトを作成したので、これまでに持っているものをバックアップして、すべてが保存されていることを確認しましょう。コマンドを実行します:

sudo backup
繰り返しになりますが、これはこれまでのところあなたの仕事を救います。頻繁にバックアップを実行して作業を保存することをお勧めします。バックアップジョブを自動的に実行することもできます。 Cronと呼ばれるUNIXユーティリティを使用してこれを行うことができます。このユーティリティを有効にするには、次のコマンドを実行してパスワードを入力してください。

sudo crontab -e
Nanoのオプション1をまだ選択していない場合は、既に慣れているテキストエディターを使用して、矢印キーを使用してファイルの下部にスクロールします。次の行を追加します。

0 * * * * sudo backup
Cronは、フォーマット分、時間、月、月、曜日を使用します。ここでは、 *または数値がコマンドを実行するタイミングを表します。 1分間に0を使用し、残りのオプションで *を使用すると、1分の開始時に1時間ごとにコマンドを実行できます。これにより、コードを自動的にバックアップできます。 sudoがrootとして実行されたときに実行された場合、Cronのすべての仕事があるため、1時間ごとにパスワードを入力する必要はありません。 パスワードを使用せずにコードを簡単にバックアップできるようにするには、バックアップコマンドのパスワードを無効にしましょう。これを行い、次のコマンドを実行し、パスワードを入力します。

sudo visudo
次に、ファイルの下部にスクロールして、別の行を追加しましょう。

ALL ALL=NOPASSWD: /bin/backup
これにより、パスワードなしでコマンド「バックアップ」をユーザーとして実行できます。このための形式は簡単で、「すべて= nopasswd:/bin/」の行をプレフィックスし、/usr/bin/に存在する/bin/backupなどのコマンドで終了します。 それでは、電子メールの操作を始めましょう。ウェブサイトをより安全に保ち、ユーザーが実在の人物であり、顧客に市場やサービスでさえあることを確認する方法であるため、ウェブサイトにとってメールは本当に重要です。インターネットを頻繁に頻繁に訪れる多くの人が毎日メールをチェックし、興味のある製品やサービスに関するあらゆる種類のマーケティングメールを受け取ります。DjangoのWebサイトで電子メールを有効にすることに関しては、いくつかのオプションがあります。どちらがあなたに最適か。 まず、ドメインから電子メールを送信し、最小限のコードが必要な電子メールサービスの支払いを行うことができます。 Google Workspace、SendInBlue、Mailgunなど、これを提供する多くのサービスがあります。 そうでなければ、あなたは建物から十分に外れていますサーバー内の自分の電子メールサービスはゼロから。このオプションは、より多くのコードであり、特別なホスティングが必要になる場合でもお勧めします。自宅のコンピューターからメールサーバーを起動することはできないようになる可能性が高いため、クラウド内のサーバーを起動して内部で独自のメールサーバーを作成する前に、構成とコードを調べて電子メールを送信してみましょう。 まず、次のようにsettings.pyを編集します

nano app/settings.py
ここで、アプリはStartAppで作成したアプリの名前です。 次の行を追加します。

SITE_NAME = 'Django App'

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'localhost'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_ADDRESS = username@server.com'
EMAIL_HOST_USER = 'username'
EMAIL_HOST_PASSWORD = config['EMAIL_HOST_PASSWORD']
DEFAULT_FROM_EMAIL = '{} <{}>'.format(SITE_NAME, EMAIL_HOST_USER)
アプリを展開する準備ができたら、これらを必ず変更してください。これを後で再検討します。 email_addressの設定は、送信したい電子メールであり、パスワード(email_host_password)をサーバー用に生成するパスワードに設定する必要があります。設定ファイルからパスワードをロードして、次のロジックを使用してコードから締め出さないようにします。

import os
import json
with open('/etc/config.json') as config_file:
    config = json.load(config_file)
次に、次のようにNANOを使用して /etc/config.jsonで構成を備えたJSONファイルを設定しました。 ファイルを編集するには:

sudo nano /etc/config.json
次の行を追加します。

{
	“EMAIL_HOST_PASSWORD”: “<some password here>”
}
[構成ファイルの編集]を引き続き編集し、アプリで使用するすべてのパスワードとキーを追加します。とりあえず、Pythonを使用して電子メールを送信する方法をすばやく調べてみましょう。まず、ユーザーに送信できる検証メールのテンプレートを作成し、ユーザーテンプレートディレクトリに配置しましょう。このテンプレートはHTMLで記述されます。

nano users/templates/users/verification_email.html
 
<h1>Django App - Verify Your Email</h1>
<p>Dear {{ user.username }},</p>
<p>To verify your email, please <a href="{{ base_url }}{% url 'users:activate' uidb64=uid token=token %}">click here</a>.</p>

<p>Alternatively, you can paste the following link in your browser's address bar:</p>
<p>{{ base_url }}{% url 'users:activate' uidb64=uid token=token %}</p>

<p>The link will expire in 30 minutes.</p>
<p>If you have not requested a verification email you can simply ignore this email.</p>
<p>See you there,</p>
<p>Daisy</p>
 
このメールはかなり簡単です。ユーザーのコンテキスト、サイトのベースURL、およびユーザーのメールの検証に使用されるユーザーIDとトークンが必要です。テンプレートをレンダリングするためにPythonコードを書く前に、settings.pyでベースURLを定義してください。先に進み、次の行をapp/settings.pyに追加します。

SITE_NAME = 'Django App'
PROTOCOL = 'https'
DOMAIN = 'example.com'

BASE_URL = PROTOCOL + '://' + DOMAIN
最終的に、サイトがインターネットの準備ができていて、展開すると、サイトを表すために購入するドメイン名としてドメインを定義する必要があります。これは、サイトにアクセスするためにNavbarに入力する名前です。今のところ、ドメインを空白のままにしたり、プレースホルダーを使用したりできます。また、Site_nameを選択した名前に変更する名前に変更する必要があります。 電子メールを送信する前に、トークンジェネレーターを作成して、決して期限切れにならないアカウントアクティベーショントークンを作成できます。これを行うことができます。これは、以下のように見えるアカウントアクティベーショントークンをインポートすることで行うことができます。ファイルを編集します:

nano users/tokens.py
次のコードを追加します。

from django.contrib.auth.tokens import PasswordResetTokenGenerator
import six
class TokenGenerator(PasswordResetTokenGenerator):
    def _make_hash_value(self, user, timestamp):
        return (
            six.text_type(user.pk) + six.text_type(timestamp)
        )
account_activation_token = TokenGenerator()
unsubscribe_token = TokenGenerator()
この基本的なトークンジェネレーターは、ユーザーをURLに送信できるトークンを生成し、ユーザーは電子メールを確認してアカウントをアクティブにするために使用できます。 次に、メールの送信方法を見てみましょう。 nanoを使用して、ユーザー/email.pyを編集します。

nano users/email.py
検証HTMLメールを送信すると、次のようになります。

from django.contrib.auth import get_user_model
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.contrib.sites.shortcuts import get_current_site
from django.core.mail import send_mail
from django.template.loader import render_to_string
from django.utils.encoding import force_bytes
from django.core.mail import EmailMultiAlternatives
from django.shortcuts import render
from .tokens import account_activation_token
from django.template.loader import render_to_string
from django.utils.html import strip_tags
from django.template import Template, Context
from django.conf import settings
import traceback

def send_verification_email(user):
    User = get_user_model()
    mail_subject = '[{}] Activate your account.'.format(settings.SITE_NAME)
    html_message = render_to_string('users/verification_email.html', {
        'user': user,
        'domain': settings.DOMAIN,
        'protocol': 'https',
        'uid': urlsafe_base64_encode(force_bytes(user.pk)),
        'token': account_activation_token.make_token(user),
    })
    send_html_email(user, mail_subject, html_message)
これはかなり簡単です。電子メールを送信し、テンプレートと設定で電子メールをレンダリングする必要がある関数をインポートし、テンプレート名で電子メールを定義し、関数を使用してユーザーに送信します。メールを送信する機能を定義していないことがわかります。

def send_html_email(user, mail_subject, html_message):
    to_email = user.email
    username = user.username
    if to_email == '':
        return None
    unsub_link = settings.BASE_URL + user.profile.create_unsubscribe_link()
    html_message = html_message + "<p><a href=\"" + unsub_link +  "\" + title=\"Unsubscribe from " + settings.SITE_NAME + " emails\">Unsubscribe</a></p></body></html>"
    msg = EmailMultiAlternatives(mail_subject, strip_tags(html_message), settings.DEFAULT_FROM_EMAIL, [to_email], headers={'List-Unsubscribe' : '<' + unsub_link + '>'},)
    msg.attach_alternative(html_message, "text/html")
    profile = user.profile
    try:
        msg.send(fail_silently=False)
        if not profile.email_valid:
            profile.email_valid=True
            profile.save()
    except:
        profile.email_valid=False
        profile.save()
これはもう少し複雑であり、このコードのすべてをまだ実行する準備ができていません。 unsub_linkを定義していることに注意してください。ユーザーが電子メールから登録解除に使用できるリンク。これは重要です。なぜなら、ユーザーはいつでもそれらを見たくない限り、ユーザーが私たちのメールをオプトアウトできる必要があるからです。また、メッセージに代わるテキストを追加します。これは、HTMLタグを削除したHTMLメッセージです。最後に、電子メールが送信されたかどうかを確認しましたが、そうでない場合は、ユーザーのプロファイルで、電子メールが有効でないことをマークします。 これをすべて機能させることができるように、ユーザーモデルに戻りましょう。登録解除へのリンクを生成する関数を定義し、ユーザーのメールが無効であることをマークするブールフィールドを定義する必要があります。 まず、ユーザー/models.pyのトップに次のインポートを追加します

nano users/models.py

# …
from django.core.signing import TimestampSigner, BadSignature, SignatureExpired
from django.urls import reverse
次に、ユーザーモデルに関数を追加してトークンを作成し、電子メールのアクティブ化に使用されるトークンと、ユーザーがメールを正常に受信しているかどうかを保存するフィールドを確認しましょう。ユーザー/models.pyでは、モデルの最後に次のコードを追加します(インデントコード)

# …
    email_valid = models.BooleanField(default=True)
    
    def make_token(self):
        return TimestampSigner().sign(self.user.username)

    def check_token(self, token):
        try:
            key = '%s:%s' % (self.user.username, token)
            TimestampSigner().unsign(key, max_age=60 * 60 * 24 * 30) # 30日間有効です
        except (BadSignature, SignatureExpired):
            return False
        return True

    def create_unsubscribe_link(self):
        username, token = self.make_token().split(":", 1)
        return reverse('users:unsubscribe', kwargs={'username': username, 'token': token,})
これはかなり簡単です。基本的な暗号化ツールであるタイムスタンプシグナーを使用して、一定の時間後に期限切れになるトークンを作成し、別の関数を使用して有効かどうかを確認します。これらのトークンを2回使用して、メールを検証し、1回は登録解除リンクを使用します。 これらを手に入れたので、私たちがする必要がある最後の仕事は見解です。ユーザー/views.py内で、ビューを追加して、メールアドレスを確認し、登録解除します。

nano users/views.py
まず、次のインポートを追加します。私はいくつかの余分なものを投げたので、後でもう一度アイテムを再度インポートする必要はありません。

from django.contrib.auth import logout
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.models import User
from django.utils.encoding import force_str
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
import json
import requests
import datetime, traceback
from django.contrib import messages
from .models import Profile
from django.utils import timezone
from django.views.decorators.cache import never_cache
from .email import send_verification_email # 確認電子メールの送信機能をインポートしてください
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.utils.decorators import method_decorator
from django.http import HttpResponseRedirect
from django.conf import settings
from django.utils import timezone
import datetime
import pytz
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
from django.contrib.auth.tokens import default_token_generator
from django.utils.http import urlsafe_base64_decode
from .tokens import account_activation_token
これらの輸入品のいくつかはすでにあるかもしれませんが、それらを繰り返すことは害はありません。他のインポートの中でも、users.tokensからのaccount_activation_tokenだけでなく、確認メールの送信機能をインポートする必要があります。 次に、ファイルの下部に、次のコードを追加します。

def unsubscribe(request, username, token):
    user = get_object_or_404(User, username=username)
    if((request.user.is_authenticated and request.user == user) or user.profile.check_token(token)):
        # それらを登録解除します
        profile = user.profile
        profile.subscribed = False
        profile.save()
        return render(request, 'users/unsubscribe.html')
    # それ以外の場合は、ログインページにリダイレクトします
    messages.warning(request,f'Your unsubscribe link has expired. Please log in to unsubscribe.')
    next_url = reverse('users:unsubscribe', kwargs={'username': username, 'token': token,})
    return HttpResponseRedirect('%s?next=%s' % (reverse('login'), next_url))

def activate(request, uidb64, token):
    try:
        uid = force_str(urlsafe_base64_decode(uidb64))
        user = User.objects.get(pk=uid)
    except(TypeError, ValueError, OverflowError, User.DoesNotExist):
        user = None
    ip = get_client_ip(request)
    if user is not None and account_activation_token.check_token(user, token):
        user.profile.email_verified = True
        user.profile.save()
        user.save()
# sendwelcomemail(リクエスト、ユーザー)
        messages.success(request, f'Thanks for confirming your email! You can now log into your account, and a welcome email has been sent to you.')
        return redirect(user.profile.create_face_url())
    else:
        messages.success(request, f'Your activation link has expired. Please request a new activation link.')
        return redirect('verify:verify')

def resend_activation(request):
    if request.method == 'POST':
        form = ResendActivationEmailForm(request.POST)
        email = request.POST['email']
        try:
            user = User.objects.get(email=email)
            send_verification_email(user)
            messages.success(request,'Your verification email sent. Please click the link in your email to verify your account.')
            return redirect(reverse('verify:verify'))
        except:
            messages.warning(request,f'Your email is not correct. Please try again.')
    else:
        form = ResendActivationEmailForm()
    return render(request,'users/resend_activation.html',{'form': form, 'title': 'Resend Activation', 'small': True})
これはたくさんのコードです。それを分解しましょう。最初の機能は、クリーンでシンプルで、メーリングリストからユーザーを登録解除します。 2番目の関数は電子メールをアクティブにし、コメント機能のsendwelcomemailを追加したことに気付くでしょう。メールテンプレートと関数の定義を使用してウェルカムメールを送信できます。まだ行っていません。アクティベーションメールの有効期限が切れるため、私が投げた最後の関数は重要です。したがって、アクティベーションメールをいつか再送信する必要があります。これには基本的なフォームを使用して、関数を呼び出して確認メールを送信できます。これを行う前に、レジスタビューに関数呼び出しを追加して、最初に送信されるようにしましょう。レジスタビューのリダイレクト、DEFレジスタ、ユーザー/Views.pyの直前にこの行を追加します。

nano users/views.py

# …(後)defレジスタ(リクエスト):
            send_verification_email(user)
# …(前)リダイレクト(
そのコードスニペットに最初と最後の行を追加する必要はありません。レジスタビューが検証メールをユーザーに送信していることを確認してください。このように見えるはずです:

# …金額
from .forms import UserRegisterForm

def register(request):
    if request.method == “POST”:
        form = UserRegisterForm(request.POST)
        if form.is_valid():
            user = form.save()
            send_verification_email(user) # この行を追加してください!
            messages.success(request, 'Welcome to the app, {}.'.format(user.username))
    return render(request, 'users/register.html', {'form': UserRegisterForm})
次に、アクティベーションメールを再送信するためにフォームを追加する必要があります。ユーザー/forms.pyで、次のフォームを追加します。

# …(金額)
class ResendActivationEmailForm(forms.Form):
    email = forms.EmailField(required=True)
また、この再送信メールアクティベーションフォームに対応するテンプレートも必要です。このテンプレートを追加しましょう。ファイルを編集します。

nano users/templates/users/resend_activation.html
次に、次のコードをファイルに追加します。

{% extends 'base.html' %}
{% block content %}
{% load crispy_forms_tags %}
        <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Resend activation email</legend>
                {{ form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-secondary" type="submit">Resend activation email</button>
            </div>
        </form>
{% endblock %}
ええ、それはたくさんです!これで、サーバーにコードを展開すると、HTMLメールを送信して、電子メールをクリックしてユーザーアカウントをアクティブ化できます。また、簡単なウェルカムメールを送信したいと思うかもしれませんので、それを行う方法を見てみましょう。ユーザー/email.pyに戻り、次のコードを追加します。

def sendwelcomeemail(user):
    User = get_user_model()
    html = open('{}/users/welcome_email.html'.format(settings.BASE_DIR)).read()
    subject = 'Welcome to ' + settings.SITE_NAME + ', {{ username }}!'
    template = Template(html)
    subjtemplate = Template(subject)
    context = Context({'username': user.username, 'base_url': settings.BASE_URL, 'model_name': 'Daisy Holton, 'site_name': settings.SITE_NAME})
    renderedtemplate = template.render(context)
    subjcontext = Context({'username': user.username})
    subjrenderedtemplate = subjtemplate.render(subjcontext)
    send_html_email(user, subjrenderedtemplate, renderedtemplate)
また、この情報をすべてレンダリングするためのテンプレートが必要です。私のウェブサイトでは、テンプレートは以下のように見えますが、好きなようにフォーマットすることを歓迎します。
 
<html>
<body>
<h3>Welcome to {{ site_name }}</h3>
<p>Hello {{ username }},</p>
<p>We are happy to see you here! Thank you for joining {{ site_name }} and being a part of the fun. To get started, here are a few things you can do after you verify your identity.</p>
<ol>
    <li><a href="{{ base_url }}/" title="Use the app">Use the app</a>. This is the main page of {{ site_name }}</li>
    <li><a href="{{ base_url }}/feed/profile/Clementine/" title="See my profile">Visit my private {{ site_name }} profile</a>. This is a page for anyone wanting to get to know me.</li>
    <li><a href="{{ base_url }}/feed/profiles/" title="See all profiles currently on the site">More profiles</a>. You can find these people on the site, and see their content.</li>
    <li><a href="{{ base_url }}/feed/all/" title="See everything on {{ site_name }}">See all posts here</a>. This is the private front page of {{ site_name }}.</li>
</ol>
<p>There is even more on the site, so feel free to visit and see what you find. You can share the site with any of the social buttons on each page. I hope you enjoy your time with {{ site_name }}! Thanks for being here.</p>
<p>With much love,</p>
<p>{{ model_name }}</p>
<a href="{{ base_url }}" title="{{ site_name }}">{{ base_url }}</a>
 
HTML Unsubscribeリンクを追加するときにこれらを追加するため、閉じたボディまたはHTMLタグがないことに注意してください。これらは重要ですが、2回定義したくありません。 では、次は何ですか?私たちは長い道のりを歩んできました。本当に、サイトをサーバーに展開する準備ができている必要があります。 @Login_Requiredデコレーターを追加して、ビューを安全にし、ユーザーのサインアップを取得し、準拠した電子メールとキャッシュ情報を送信できます。さらにいくつかの便利な機能を追加し、コードをリモートサーバーに展開し、メールサーバー、ドメイン構成、フィルターを設定してサイトを安全かつ適切にするための基礎を構築します。 また、パスワードリセットビューも必要なので、それを本当に迅速に追加しましょう。 Djangoの内蔵パスワードリセットビューはいくつかの関数で壊れていますが、独自のビュー、電子メールテンプレート、フォーム、およびURLパターンを書く方法について説明します。ユーザー/views.pyでは、ビューがどのように見えるかを次に示します

# ...金額
from django.contrib.auth.tokens import default_token_generator
from django.contrib.auth.forms import SetPasswordForm
from django.utils.http import urlsafe_base64_decode

def password_reset(request, uidb64, token):
    user = get_object_or_404(User, id=urlsafe_base64_decode(uidb64))
    if request.method == 'POST':
        form = SetPasswordForm(user, request.POST)
        if form.is_valid() and default_token_generator.check_token(user, token):
            form.save()
            messages.success(request, 'Your password has been reset.')
        elif not form.is_valid():
            messages.warning(request, 'Your passwords do not match, or do not meet the requirements. Please try again.')
            return redirect(request.path)
        else:
            messages.warning(request, 'Your password reset link has expired. Please create a new one.')
        return redirect(reverse('users:login'))
    return render(request, 'users/password_reset_confirm.html', {
        'title': 'Reset your Password',
        'form': SetPasswordForm(user)
このフォームはdjangoに組み込まれていますが、パスワードのリセット、ユーザー/テンプレート/ユーザー/password_reset_confirm.htmlを確認するためのテンプレートが必要です
 
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
        <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Reset Password</legend>
                {{ form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-info" type="submit">Reset Password</button>
            </div>
        </form>
{% endblock content %}
 
また、ユーザー/テンプレート/ユーザー/password_reset.htmlで、シンプルなフォームのパスワードリセットメールを送信するテンプレートもあります。
 
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
        <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Reset Password</legend>
                {{ form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-info" type="submit">Request Password Reset</button>
            </div>
        </form>
{% endblock content %}
 
電子メール自体のテンプレートは簡単です。これは、ユーザー/テンプレート/ユーザー/password_reset_email.htmlでパスワードをリセットするためのリンクをレンダリングする基本的なHTMLファイルです。 Djangoはこのファイルを自動的に解釈します。
 
<h1>Uglek - Reset Your Password</h1>
<p>Hello,</p>
<p>To reset your password, please <a href="https:/uglek.com{% url 'password_reset_confirm' uidb64=uid token=token %}">click here</a>.</p>
<p>Alternatively, you can paste the following link into your browser:</p>
<p>https://uglek.com{% url 'password_reset_confirm' uidb64=uid token=token %}</p>
<p>If you have not requested a password reset you can simply ignore this email.</p>
<p>Thanks for joining us,</p>
<p>Daisy</p>
 
さらに2つのテンプレートも必要です。 1つ目は、電子メールが送信されたことを確認することです。これらのビューはすでにDjangoにあるので、urls.pyでそれらに対処する必要があります。このテンプレートは、users/templates/users/password_reset_done.htmlにあります
 
{% extends 'base.html' %}
{% block content %}
  <div class="media-body">
    <div class="alert alert-info">
        An email has been sent with instructions to reset your password.
    </div>
  </div>
{% endblock content %}
 
そして最後に、パスワードのリセットが完了していることを確認するために、ユーザー/テンプレート/ユーザー/Password_reset_complete.html
 
{% extends 'base.html' %}
{% block content %}
 <div class="media-body">
    <div class="alert alert-info">
        Your password has been set.
    </div>
    <a href="{% url 'users:login' %}">Sign In Here</a>
  </div>
{% endblock content %}
 
これで、これらのビューにはURLパターンが必要です。ユーザー/urls.pyで、次のURLパターンを追加します。

urlpatterns = [
    # ...以前のURLはここにあります
    path('password-reset/',
         auth_views.PasswordResetView.as_view(
             template_name='users/password_reset.html',
             html_email_template_name='users/password_reset_html_email.html'
         ),
         name='password_reset'),
    path('password-reset/done/',
         auth_views.PasswordResetDoneView.as_view(
             template_name='users/password_reset_done.html'
         ),
         name='password_reset_done'),
    path('password-reset-confirm/<uidb64>/<token>/',
         auth_views.PasswordResetConfirmView.as_view(
             template_name='users/password_reset_confirm.html'
         ),
         name='password_reset_confirm'),
    path('password-reset-complete/',
         auth_views.PasswordResetCompleteView.as_view(
             template_name='users/password_reset_complete.html'
         ),
         name='password_reset_complete'),
]
4つのテンプレート、それはたくさんです!しかし、今では、必要なときに、すべてがWebブラウザーからユーザーのパスワードをリセットできるようにすることができます。 これはたくさんのコードであることを理解しています。それがあなたの頭の上に少し見えるなら、それは大丈夫です。あなたは改善し、あなたの理解が改善され、あなたはすぐにコードにもっと能力を尽くすようになります。あなたが完全に迷子になっている場合は、自己ペースの学習をオンラインでコード化するために学習した後、後でこのソフトウェアに戻ることをお勧めします。これらは通常、自由に始めることができ、このプロジェクトに戻ったときに成功するために必要なすべてを案内します。続行する準備ができていると感じている場合は、読み進めてください。次に、コードの展開をリモートサーバーに展開してメールサーバーを設定し、Bashを使用して展開を自動化して、いつでも新しいプロジェクトを設定できるようにします。いくつかの簡単なコマンド。 リモートサーバーに展開する前に最後に行う必要があることは、サイトをもう少し安全にすることです。あなたはログインビューはユーザー名とパスワードのみを使用し、マルチファクター認証またはワンタイムコードがないことに注意してください。これは簡単な修正であり、同じコードを使用すると、サイトにテキストメッセージを送信し、サーバーに送信されたテキストメッセージに応答することもできます。まず、ユーザーモデルに戻り、各ログインを表すタイムスタンプ署名者を追加します。また、ログインに追加のセキュリティを追加するために使用されるユニークで回転識別子をユーザーモデルに追加します。ユーザーモデル、ユーザー/モデル.pyの編集、以下を追加します

from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
# UUID、タイムスタンプの署名者、URLジェネレーターを必ずインポートしてください(逆)
import uuid
from django.core.signing import TimestampSigner, BadSignature, SignatureExpired
from django.urls import reverse

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True, related_name='profile')
    account_created = models.DateTimeField(default=timezone.now)
    last_seen = models.DateTimeField(default=timezone.now)
    can_login = models.DateTimeField(default=timezone.now)
    preferred_name = models.CharField(max_length=20,default='', null=True, blank=True)
    bio = models.TextField(blank=True, default='')
    # このコードをここに追加します
    uid = models.CharField(max_length=32, default=uuid.uuid4, null=True, blank=True)
    mfa_enabled = models.BooleanField(default=False)
    enable_mfa = models.BooleanField(default=False)
    phone_number = models.CharField(default='', null=True, blank=True, max_length=15)
    verification_code = models.CharField(default='', null=True, blank=True, max_length=15)
    verification_code_length = models.IntegerField(default=6)
    mfa_code_expires = models.DateTimeField(default=timezone.now)
    mfa_attempts = models.IntegerField(default=0)

    def make_auth_token(self):
        return TimestampSigner().sign(self.uid)

    # この関数を追加します
    def create_auth_url(self):
        username, token = self.make_auth_token().split(":", 1)
        return reverse('users:mfa', kwargs={'username': username, 'token': token,})

    def check_auth_token(self, token):
        try:
            key = '%s:%s' % (self.uid, token)
            TimestampSigner().unsign(key, max_age=60 * settings.AUTH_VALID_MINUTES) # 3分間有効です
        except (BadSignature, SignatureExpired):
            return False
        return True
コメント(#の行のコード)に加えて、ユーザー/Models.pyがこのように見えることを確認してください。これを分解すると、それは簡単です。いくつかのインポートがあります。これは、安全なコードを生成し、それが有効であることを確認するために検証できる暗号化されたユーティリティであるタイムスタンプシグナーです。また、トークンの署名でユーザーを識別する一意の識別子と、トークンがユーザーに送信されるURLでUUIDを使用します。この基本的な暗号化を使用して、2因子認証ビューを構築します。他のことをする前に、ユーザーモデルが更新されるように移行を実行しましょう。 manage.pyを使用したディレクトリで、次のコマンドを実行して移行を完了します。

source venv/bin/activate
python manage.py makemigrations && python manage.py migrate
これは重要です。モデルを変更するたびに、モデルを実際に使用できるようにする前に、テーブルを作成し、デフォルトでデータベースを更新する必要があるためです。 次に、ログインビューを即興で即興で、二次認証ビューにリダイレクトしましょう。ユーザー/views.pyで、ログイン関数を削除し、ユーザーモデルで生成したばかりのURLにリダイレクトします。

# …金額

def login(request):
    if request.method == “POST”:
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(username=username, password=password)
        if user and user.profile.can_login < timezone.now(): # ユーザーがログインできるかどうかを確認することに注意してください
            # ここにあるauth_login関数を削除します
            messages.success(request, 'Your password was accepted. Please continue.')
            if user.profile.mfa_enabled:
                return redirect(user.profile.create_auth_url()) # 注意してください。ここで新しいURLにリダイレクトします
            else: # ユーザーがマルチファクター認証を使用していない場合は、それらをログインするだけです。
                auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend')
                return redirect('feed:feed')
        else: # ログインが成功しなかった場合、
            messages.warning(request, 'Username or password incorrect. Please try again.')
            user = User.objects.filter(username=username).first() # これはユーザープロファイルを更新する部分です
            if user: 
                profile = user.profile
                profile.can_login = timezone.now() + datetime.timedelta(seconds=15) # だから彼らは数秒間再びログインすることはできません
                profile.save()
    return render(request, 'users/login.html', {'form': AuthenticationForm()})
これは非常に簡単です。これは、作成時に2つの要因認証ビューにリダイレクトする方法があります。また、ユーザーが電話番号を追加していない場合に備えて、フォールバックもあります。基本的なビューを追加して電話番号をすぐに追加し、すぐにテキストメッセージでログインします。 まず、コードからテキストメッセージを送信する簡単な方法が必要です。これを行うには、多くのAPIから選択できますが、私の意見で最も簡単なAPIはTwilioです。また、小規模なプロジェクトやバルク割引の優れた価格設定も提供しています。 twilio.comでアカウントを作成し、プロジェクトの詳細を入力し、電話番号を購入し、settings.pyにAPIキーをコピーします。次に、このコードを新しいファイル、ユーザー/sms.pyの下に追加します。

nano users/sms.py

# 必要なすべてのパッケージをインポートします
from django.utils import timezone
import random
import datetime
from django.conf import settings
from feed.middleware import get_current_request
from django.contrib import messages
import traceback

account_sid = settings.TWILIO_ACCOUNT_SID
auth_token = settings.TWILIO_AUTH_TOKEN
source_phone = settings.PHONE_NUMBER

# このコードは、Twilioでテキストを送信します
def send_text(target_phone, text):
    from twilio.rest import Client
    try:
        client = Client(account_sid, auth_token)
        if len(target_phone) >= 11:
            message = client.messages.create(
                to=target_phone,
                from_=source_phone,
                body=text)
    except:
        print(traceback.format_exc())

# 非常に多くの数字で数字を取得するヘルパー機能
def get_num_length(num, length):
    n = ''
    for x in range(length):
        n = n + str(num)
    return int(n)

# テキストを送信して、ユーザーを確認します
def send_verification_text(user):
    length = user.profile.verification_code_length
    code = random.randint(get_num_length(1, length), get_num_length(9, length));
    user.profile.verification_code = code
    user.profile.mfa_code_expires = timezone.now() + datetime.timedelta(minutes=3)
    user.profile.save()
    send_user_text(user, "Your verification code for {} is {}".format(settings.SITE_NAME, str(code)))

# この関数のテキストをユーザーに送信します
def send_user_text(user, text):
    send_text(user.profile.phone_number, text)

# この関数でコードを検証します
def check_verification_code(user, code):
    user.profile.mfa_attempts += 1
    result = user.profile.verification_code != None and code != '' and user.profile.verification_code == code and user.profile.mfa_code_expires > timezone.now() and user.profile.mfa_attempts <= 3
    if user.profile.mfa_attempts < 3 and result:
        user.profile.verification_code_length = 6
    elif user.profile.mfa_attempts > 2 and not result:
        user.profile.verification_code_length = 8
    user.profile.save()
    return result

# 時間を検証します
def check_verification_time(user):
    result = user.profile.mfa_code_expires > timezone.now()
    return result
設定を適切に変更して、これらの行をキーに追加してください。

# Twilioダッシュボードからこれらをコピーしてください
TWILIO_ACCOUNT_SID = “<your sid>”
TWILIO_AUTH_TOKEN = “<your token>”
PHONE_NUMBER = “<your twilio phone number>”
SITE_NAME = “<Your site name>”
AUTH_VALID_MINUTES = 3 # TFAページがインスタンス化されるとアクティブになります
まず、2つの要因認証ビューにフォームが必要になります。ユーザー/forms.pyの編集、次のコードを追加します。

# …金額
from django import forms

# 電話番号を入力するためのフォーム
class PhoneNumberForm(forms.Form):
    phone_number = forms.RegexField(regex=r'^\+?1?\d{9,15}$', error_messages = {'invalid': "Phone number must be entered in the format: '+999999999'. Up to 15 digits is allowed."})
    def __init__(self, *args, **kwargs):
        super(PhoneNumberForm, self).__init__(*args, **kwargs)
        self.fields['phone_number'].label = phone_number_label

# 認証のためのフォーム
class TfaForm(forms.Form):
    code = forms.IntegerField(required=False)
    def __init__(self, *args, **kwargs):
        super(TfaForm, self).__init__(*args, **kwargs)
        self.fields['code'].widget.attrs.update({'autocomplete': 'off'})
    help_texts = {
        'code': 'Please enter the six digit code after sending it to your phone with the button above.'
    }
次に、ユーザー/Views.pyでビューを作成しましょう

# …金額
from django.http import HttpResponseRedirect
from .forms import PhoneNumberForm, TfaForm

def mfa(request, username, token):
    user = User.objects.filter(profile__uuid=username).first()
    if not user: return HttpResponseRedirect(reverse('verify:age') + '?next=' + request.GET.get('next') if request.GET.get('next') else '/go/' if request.user.is_authenticated and request.user.profile.vendor else '/' if request.user.is_authenticated else reverse('users:login'))
    user = get_object_or_404(User, profile__uuid=username)
    next = request.GET.get('next','')
    if not user.profile.mfa_enabled:
        if not check_verification_time(user):
            user.profile.mfa_enabled = False
            user.profile.enable_two_factor_authentication = True
            user.profile.phone_number = '+1'
            user.profile.save()
            print('Logging in user')
            auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend')
            messages.warning(request, 'Please enter a valid phone number and verify it with a code.')
            return redirect(reverse('users:mfa_onboarding'))
    if request.method == 'POST':
        form = TfaForm(request.POST)
        code = form.data['code']
        if code and code != '' and code != None:
            token_validated = user.profile.check_auth_token(token)
            p = user.profile
            is_verified = check_verification_code(user, int(code))
            p.mfa_authenticated = is_verified
            if token_validated:
                if is_verified:
                    user.profile.mfa_enabled = True
                    user.profile.save()
                    auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend')
                    p.verfication_code = None
                    p.uid = get_uuid()
                    p.save()
                    messages.success(request, 'You have been authenticated. Welcome.')
                    qs = '?'
                    for key, value in request.GET.items():
                        qs = qs + key + '=' + value + '&'
                    if next != '' and not (next.startswith('/accounts/logout/') or next.startswith('/accounts/login/') or next.startswith('/admin/login/') or next.startswith('/accounts/register/')):
                        return HttpResponseRedirect(ext)
                    elif next.startswith('/accounts/logout/') or next.startswith('/accounts/login/') or next.startswith('/accounts/register/'):
                        return redirect('feed:feed')
                    elif request.META.get('HTTP_REFERER', '/').startswith('/accounts/login/'):
                        return redirect(reverse('feed:feed'))
                    elif not next:
                        return redirect(reverse('feed:feed')
                    else:
                        return HttpResponseRedirect('feed:feed')
                else:
                    messages.warning(request, 'The code you entered was not recognized. Please try again.')
            elif not token_validated:
                messages.warning(request, 'The URL token has expired or was not recognized. Please try again.')
                logout(request)
                return redirect(reverse('users:login'))
            if p.mfa_attempts > 3:
                messages.warning(request, 'You have entered the incorrect code more than 3 times. please send yourself a new code.')
                p.verification_code = None
                p.save()
        elif user.profile.can_send_mfa < timezone.now():
            user.profile.mfa_attempts = 0
            user.profile.can_send_mfa = timezone.now() + datetime.timedelta(minutes=2)
            user.profile.save()
            send_verification_text(user)
            messages.success(request, "Please enter the code sent to your phone number. The code will expire in 3 minutes.")
        else:
            messages.warning(request, 'You are sending too many two factor authentication codes. Wait a few minutes before sending another code.')
    form = TfaForm()
    hide_logo = None
    if user.profile.hide_logo:
        hide_logo = True
    return render(request, 'users/mfa.html', {'title': 'Enter Code', 'form': form, 'xsmall': True, 'user': user, 'hide_logo': hide_logo, 'accl_logout': user.profile.shake_to_logout, 'preload': False})

@login_required
def mfa_onboarding(request):
    if request.method == 'POST':
        form = PhoneNumberForm(request.POST)
        request.user.profile.phone_number = form.data['phone_number'].replace('-', '').replace('(','').replace(')','')
        request.user.profile.mfa_enabled = True
        request.user.profile.enable_two_factor_authentication = True
        request.user.profile.save()
        messages.success(request, 'You have added a phone number to your account.')
        user = request.user
        return redirect(user.profile.create_auth_url())
    form = PhoneNumberForm(initial={'phone_number': request.user.profile.phone_number if request.user.profile.phone_number else '+1'})
    return render(request, 'users/mfa_onboarding.html', {'title': 'Enter your phone number', 'form': form, 'small': True})
また、これらのビューの両方にテンプレートが必要です。最初にMFAテンプレートを追加しましょう。

nano users/templates/users/mfa.html
このHTMLコードをテンプレートに追加します
 
{% extends 'base.html' %}
{% block content %}
{% load app_filters %}
{% load crispy_forms_tags %}
        <form action="{{ request.path }}{% if request.GET.next %}?next={{ request.GET.next }}{% endif %}" method="POST">
            {% csrf_token %}
            <legend class="border-bottom mb-4">Enter Verification Code</legend>
            <p>Step 1: Send the code</p>
	    <i>Never share your code with anyone, as it can be used to access your account temporarily.</i>
	    <div class="form-group">
                <button class="btn btn-outline-primary" type="submit">Send code</button>
            </div>
	    <hr>
	    <p>Step 2: Enter the code</p>
            <fieldset class="form-group">
                {{ form|crispy }}
		<p>Press the enter button to send yourself the code at {{ user.profile.phone_number|securephone }}. Then, enter the code and press enter.</p>
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-secondary" type="submit">Enter code</button>
            </div>
        </form>
{% endblock %}
 
これはかなり自明です。フォームはコードまたは空のコードのいずれかを送信します。つまり、空のコードを受信した場合、コードを送信するビューで表示されます。次に、2つのボタンを2つだけ持っているので、どちらのボタンでコードを送信できます。次に、電話番号を追加する簡単なフォームを追加します。

nano users/templates/users/mfa_onboarding.html
次のHTMLを追加します。
 
{% extends 'base.html' %}
{% block content %}
{% load crispy_forms_tags %}
        <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Set Up Two Factor Authentication</legend>
                {{ form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-secondary" type="submit">Add phone number</button>
            </div>
        </form>
{% endblock %}
 
このフォームははるかにシンプルで、作成した電話番号フォームをレンダリングし、ユーザーが電話番号を追加できるようにします。 これは本当によさそうだ!すべてが適切にセットアップされている限り、URLパターンを追加するとすぐに、メッセージを送信し、電話番号でユーザーをログインできるはずです。セットアップする必要がある最後のことはプロファイルビューです。これにより、ユーザーがログインせずに電話番号を変更できることを確認できます。最終的には、「停止する停止」オプションを追加して、ユーザーがテキストできるようにすることをお勧めします。将来のテキストメッセージをオプトアウトする「停止」。 ユーザー/Views.pyにプロファイルビューを追加しましょう。このビューでは、ユーザーのバイオ、電子メール、ユーザー名、電話番号を更新し、マルチファクター認証を有効にすることができます。まず、ユーザー/forms.pyにさらに2つのフォームが必要になります

# ...金額
class UserUpdateForm(forms.ModelForm):
    email = forms.EmailField()
    class Meta:
        model = User
        fields = ['username', 'email']

phone_number_label = 'Phone number (no spaces, parenthesis \'(\' or dashes \'-\', numbers beginning with + only)'

class ProfileUpdateForm(forms.ModelForm):
    subscribed = forms.BooleanField(required=False)
    phone_number = forms.CharField(required=False)
    def __init__(self, *args, **kwargs):
        super(ProfileUpdateForm, self).__init__(*args, **kwargs)
    class Meta:
        model = Profile
        fields = ['bio', 'phone_number', 'enable_mfa', 'subscribed']
次に、これらのフォームの両方を使用するビューを作成できます。ユーザー/views.pyを編集し、ビューを追加します。

# これらのインポートを追加します
from .forms import UserUpdateForm, ProfileUpdateForm
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_exempt
from .models import Profile
from .mfa import send_user_text

@csrf_exempt
@never_cache
@login_required
def profile(request):
    if request.method == 'POST':
        u_form = UserUpdateForm(request.POST, instance=request.user)
        p_form = ProfileUpdateForm(request.POST,
                                       request.FILES,
                                       instance=request.user.profile)
        if u_form.is_valid() and p_form.is_valid():
            new_phone_number = p_form.data['phone_number']
            u_form.save()
            profile = p_form.save(commit=False)
            profile.phone_number = profile.phone_number.replace('-', '').replace('(','').replace(')','')
            profile.save()
            if new_phone_number != oldprofile.phone_number and oldprofile.phone_number and len(oldprofile.phone_number) >= 11:
                profile.mfa_enabled = True
                profile.save()
                send_text(oldprofile.phone_number, 'Your phone number has been updated to ' + new_phone_number + '. Please refer to texts on that phone to log in. If you didnt make this change, please call us. - {}'.format(settings.SITE_NAME))
            if profile.enable_two_factor_authentication and profile.phone_number and len(profile.phone_number) < 11:
                profile.enable_two_factor_authentication = False
                messages.success(request, f'Two factor authentication can\'t be activated without entering a phone number. Please enter a phone number to enable two factor authentication.')
            profile.save()
            if new_phone_number != oldprofile.phone_number and new_phone_number and len(new_phone_number) >= 11:
                send_user_text(request.user, 'You have added this number to {} for two factor authentication. You can now use your number for two factor authentication. If you didnt make this change, please call us. - {}'.format(settings.SITE_NAME, settings.DOMAIN))
                profile.mfa_enabled = True
                profile.mfa_code_expires = timezone.now() + datetime.timedelta(minutes=3)
                profile.save()
                return redirect(profile.create_auth_url())
            messages.success(request, f'Your profile has been updated!')
            print('Profile updated')
            return redirect('users:profile')
    else:
        u_form = UserUpdateForm(instance=request.user)
        p_form = ProfileUpdateForm(instance=request.user.profile, initial={'phone_number': request.user.profile.phone_number if request.user.profile.phone_number else '+1'})
    context = {
        'u_form': u_form,
        'p_form': p_form,
        'title':'Update Your Profile',
    }
    return render(request, 'users/profile.html', context)
また、このビューにはテンプレートが必要です。

nano users/templates/users/profile.html
 
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% load feed_filters%}
{% block content %}
	<h2>Edit Your Profile</h2>  
	<form method="POST" enctype="multipart/form-data" id="profile-form">
          {% csrf_token %}
          <fieldset class="form-group">
              <legend class="border-bottom mb-4 mt-4">Profile info</legend>
              {{ u_form|crispy }}
              {{ p_form|crispy }}
          </fieldset>
          <div class="form-group">
              <button class="btn btn-outline-info" type="submit">Update}</button>
          </div>
	</form>
        <p style="text-color: green;" class="hide" id="posted">Saved</p>

{% endblock content %}
{% block javascript %}
var form = document.getElementById('profile-form');
$('input').change(function(){
	var formdata = new FormData(form);
	$.ajax({
		url: window.location.href,
		type: "POST",
		data: formdata,
		processData: false,
		contentType: false,
		timeout: 1000 * 60,
                success: function(data) {
                  $(posted).removeClass("hide");
		  setTimeout(function() {
			$(posted).addClass("fade-hidden");
			setTimeout(function() {
				$(posted).addClass("hide");
				$(posted).removeClass("fade-hidden");
			}, 2000);
		  }, 2000);
                }
	});
});
{% endblock %}
 
これはかなりシンプルなフォームであることに気付くが、更新されるフォームの内容を自動的に投稿するJavaScriptが含まれている。これは有用であるため、毎回送信を押すことなく編集を行うことができます。 次に、ユーザーのURLパターンのこれらすべてのビューを表すURLが必要です。ユーザー/urls.pyを編集して、このコードを追加します。

# …以前のコード、インポート
from django.urls import path
from . import views

app_name='users'

urlpatterns = [
# …以前に入力したURLパターン、次の3行を追加します
    path('mfa/<str:username>/<str:token>/', views.mfa, name='mfa'),
    path('mfa/onboarding/', views.mfa_onboarding, name='mfa_onboarding'),
    path('profile/', views.profile, name='profile'),
]
今こそ私たちのプロジェクトをテストするのに良い時期です。しかし、最初に、別のバックアップを実行しましょう。

backup
サーバーを実行します。 Linuxサーバーに展開する前に、アカウントで2つの要因認証を有効にすることをお勧めします。これをプロファイルURL、/users/profile/、および電話番号を入力した後に認証を有効にするためにボックスをチェックしてからフォームを送信します。

python manage.py runserver localhost:8000
Webブラウザに移動してWebページにアクセスして、この例ではGoogle Chromeを使用して、url https:// localhost:8000/accounts/profile/を入力しています。 必要に応じてログインし、2つの要因認証を有効にすることができます。 このプロジェクトは、実際にメールを送信できるように、実行するサーバーが必要です。しかし、最初に、エラーを確認する方法が必要です。デバッグモードでサーバーを実行すると、settings.debugがtrueに等しい場合、サーバーはエラーを自動的に表示します。生産サーバーで安全でないデバッグモードを使用せずにエラーを表示するには、ビューを追加する必要があります。処理できる最も重要なエラーは次のとおりです。 エラー500-コードの問題 エラー404-見つからなかったページ(壊れたURL) エラー403-許可が拒否されたエラー エラーと呼ばれるこれらのエラーを処理するための新しいアプリを追加しましょう。

python manage.py startapp errors
これをinstalled_appsの設定で以前と同じようにsettings.pyに追加し、App/urls.pyのいくつかのビューへの参照を追加することから始めます。アプリはdjangoプロジェクトの名前です。

handler404 = 'errors.views.handler404'
handler500 = 'errors.views.handler500'
handler403 = 'errors.views.handler403'
これは、エラービュー、テンプレート、ミドルウェアの少し以外に必要なすべてです。それらをそう定義しましょう:

from django.shortcuts import render, redirect
from django.http import HttpResponse
from stacktrace.models import Error
from errors.middleware import get_current_exception
from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import user_passes_test
from .logs import get_logs
from face.tests import is_superuser_or_vendor
from django.views.decorators.csrf import csrf_exempt
from errors.highlight import highlight_code
from django.shortcuts import redirect
from django.urls import reverse

# ここであなたの意見を作成します。
@login_required
@user_passes_test(is_superuser_or_vendor)
def logs(request):
    logs = highlight_code(get_logs())
    return render(request, 'errors/live_error.html', {'title': 'Error Logs', 'pagetitle': 'Error Logs', 'notes': 'These are the recent error logs.', 'trace': logs, 'full': True})

@login_required
@user_passes_test(is_superuser_or_vendor)
def logs_api(request):
    logs = highlight_code(get_logs())
    return HttpResponse(logs)

@login_required
def handler404(request, exception):
    if not request.path.endswith('/'): return redirect(request.path + '/')
    return render(request, 'errors/error.html', {'title': 'Error 404', 'pagetitle': 'Error 404', 'notes': 'This page was not found on the server. It may have moved or been deleted.', 'is_404': True})

def handler500(request):
    print(get_current_exception())
    user = None
    if hasattr(request, 'user') and request.user and request.user.is_authenticated:
        user = request.user
    try:
        Error.objects.create(user=user, stack_trace=get_current_exception(), notes='Logged by 500 handler.')
    except: pass
    return render(request, 'errors/error.html', {'title': 'Error 500', 'pagetitle': 'Error 500', 'notes': 'There is a problem with the server, or with a request coming from you. Thank you for your understanding while we get things set up.', 'trace': get_current_exception()})

def handler403(request, exception):
    return render(request, 'errors/error.html', {'title': 'Error 403', 'pagetitle': 'Error 403', 'notes': 'You don\'t have permission to preform this request. If you think this is in error, please contact the server administrator.', 'is_403': True})

def handler400(request, exception):
    return render(request, 'errors/error.html', {'title': 'Error 400', 'pagetitle': 'Error 400', 'notes': 'This was a bad request.'})
次に、これらのエラーを処理するためにミドルウェアを定義しましょう。これは、最初にMiddleware_ClassesにMiddlewareの名前を付けて追加します。

MIDDLEWARE_CLASSES = [
    # ...以前のミドルウェア
    'errors.middleware.ExceptionVerboseMiddleware,
]
次に、ミドルウェアを追加しましょう。

from threading import local
import traceback
from django.utils.deprecation import MiddlewareMixin

_error = local()

class ExceptionVerboseMiddleware(MiddlewareMixin):
    def process_exception(self, request, exception):
        _error.value = traceback.format_exc()

def get_current_exception():
    try:
        return _error.value
    except AttributeError:
        return None

def set_current_exception(exception):
    try:
        _error.value = exception
    except AttributeError:
        print('Attribute error setting exception.')
関数を追加して、ローカルのスレッドを使用して現在の例外を取得します。これにより、コード内のエラーをトレースできます。テンプレートに関しては、ビューでタイトルを動的に定義するため、テンプレートは1つだけが必要です。テンプレートは、タイトルと「トレース」をレンダリングする必要があります。これは、コンテキストからのエラートレースバックです。

nano errors/templates/errors/error.html
 
{% extends 'base.html' %}
{% block content %}
<h1>{{ pagetitle }}</h1>
<p>{{ trace }}</p>
{% endblock %}
 
これは私たちの最も単純なテンプレートですが、プロジェクトのエラーを見るのは簡単です。次に、設定でデバッグを無効にしましょう。

nano app/settings.py
この行が真実に設定されている場所を見つけて、それをfalseに変更します

DEBUG = False
今すぐアプリをバックアップしてください。リモートLinuxサーバーに展開し、そこから機能を追加し続ける準備ができています。

sudo backup
このコードをサーバーに投稿する前に、コードにいくつかの問題があるかもしれないと考えるべきです。ケースに応じて、彼らに投稿された情報を受け入れるサイトには、スパムが投稿され、スパムの削除が困難になります。これはすぐには発生しないはずですが、それが起こっている場合は、後でサイトのスパムを自動的にモデレートし、ロボットがユーザーアカウントを無効にし、ユーザーの身元を確認する方法とともに、ロボットがサイトにアクセスすることをより困難にする方法を調べます。指紋や顔の認識など、IDまたは生体認証スキャンのスキャン。 生産で調べたマルチファクター認証の例を見ると、物事は異なる場合があります。ログインを制限し、トークンの期限切れにしていることに注意してください。ロボットがサイトにアクセスしている場合、ユーザーが同時にコードを入力する可能性があるため、2つの要因認証がより困難になる可能性があります。これと戦うために、ユーザーモデルのモデルを使用して、私たちがそうであるときにサイトとの対話方法を宣言しましょう電話番号でマルチファクター認証を使用して認証します。また、電子メールで認証するオプションも追加します。ユーザーモデルを編集することから始めます

nano users/models.py
これは、追加しているモデルがどのように見えるかです。 ID、ユーザー、タイムスタンプ、有効期限、長さ、およびマルチファクター認証に対する試行(電話または電子メールに送信された123456などのコード)を保存するための方法だけの方法は必要ありません。

# ウェブサイトにログインするために使用される基本的なトークン
class MFAToken(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='mfa_tokens')
    timestamp = models.DateTimeField(default=timezone.now)
    expires = models.DateTimeField(default=timezone.now)
    token = models.CharField(default='', max_length=100)
    length = models.IntegerField(default=6)
    attempts = models.IntegerField(default=0)
    uid = models.CharField(default=uuid.uuid4, max_length=100)
また、ユーザーに特権を追加しましょう。最終的には特権ユーザーの自動的に移住するために移行する前に、今のところ手動で設定します。ユーザーモデルでは、プロファイルにこの行を追加します。

    vendor = models.BooleanField(default=False)
データベースの変更と同様に、DjangoでModels.pyファイルを編集するたびに移行を行い、データベースを移行する必要があります。これを行うには、最初にソースを使用します(ターミナルが開いていたのでまだ使用されていない場合)。次にpython manage.pyで移行を行い、移行します。

cd project-directory-you-named # (必要に応じて)
source venv/bin/activate
python manage.py makemigrations && python manage.py migrate
今のところ、シェルを使用してベンダーとして作成したアカウントを登録できます。

python manage.py shell
from users.models import Profile
p = Profile.objects.get(user__username='Charlotte')
p.vendor = True
p.save()
exit()
次に、このトークンを使用するためにマルチファクター認証ビューを進化させましょう。まず、MFAヘルパーユーティリティを変更する必要があります。ナノを使用して、

nano users/mfa.py

from django.utils import timezone
import random
import datetime
from django.conf import settings
from feed.middleware import get_current_request
from django.contrib import messages
from .email import send_html_email
import traceback
from .models import MFAToken

account_sid = settings.TWILIO_ACCOUNT_SID
auth_token = settings.TWILIO_AUTH_TOKEN
source_phone = settings.PHONE_NUMBER

def send_text(target_phone, text):
    from twilio.rest import Client
    try:
        client = Client(account_sid, auth_token)
        if len(target_phone) >= 11:
            message = client.messages.create(
                to=target_phone,
                from_=source_phone,
                body=text + ' Text STOP to cancel.')
    except:
        messages.warning(get_current_request(), 'There was an error sending the message.')
        print(traceback.format_exc())

def get_num_length(num, length):
    n = ''
    for x in range(length):
        n = n + str(num)
    return int(n)

def send_verification_text(user, token):
    length = user.profile.verification_code_length
    code = random.randint(get_num_length(1, length), get_num_length(9, length));
    token.token = code
    token.expires = timezone.now() + datetime.timedelta(minutes=settings.AUTH_VALID_MINUTES)
    token.save()
    send_user_text(user, "Your verification code for {} is {}".format(settings.SITE_NAME, str(code)))

def send_verification_email(user, token):
    length = user.profile.verification_code_length
    code = random.randint(get_num_length(1, length), get_num_length(9, length));
    token.token = code
    token.expires = timezone.now() + datetime.timedelta(minutes=settings.AUTH_VALID_MINUTES)
    token.save()
    send_html_email(user, "Your verification code for {} is {}".format(settings.SITE_NAME, str(code)), "<p>Dear {},</p><p>Your verification code for {} is {}. Thank you for using this code to secure your account.</p><h2>{}</h2><p>Sincerely, {}</p>".format(user.profile.name, settings.SITE_NAME, str(code), str(code), settings.SITE_NAME))

def send_user_text(user, text):
    send_text(user.profile.phone_number, text)

def check_verification_code(user, token, code):
    token.attempts = token.attempts + 1
    profile = user.profile
    result = (token != None and code != '' and token.token == code and (token.expires > timezone.now()) and token.attempts <= settings.MFA_TOKEN_ATTEMPTS)
    if token.attempts < 3 and result:
        profile.verification_code_length = 6
    elif token.attempts > 1 and not result:
        profile.verification_code_length = profile.verification_code_length + 2
        if profile.verification_code_length > settings.MFA_TOKEN_LENGTH: profile.verification_code_length = settings.MFA_TOKEN_LENGTH
    token.save()
    profile.save()
    return result

# 電子メールまたは電話番号を使用してユーザーを認証します
def mfa(request, username, usertoken):
    token = MFAToken.objects.filter(uid=username, expires__gt=timezone.now() + datetime.timedelta(seconds=30)).order_by('-timestamp').last() # URL(uuid)に渡された値によってトークンをフィルタリングします
    if not token: token = MFAToken.objects.create(user=User.objects.filter(profile__uuid=username).first(), uid=username, expires=timezone.now() + datetime.timedelta(seconds=115)) # このセッションが作成されていない場合は、作成してください
    user = User.objects.filter(id=token.user.id).first() # トークンからユーザーを取得します
    if not user and request.user.is_authenticated: return redirect(reverse('feed:home')) # それらがすでに認証されている場合は、それらをログインします
    if not user: raise PermissionDenied() # ユーザーが見つからなかった場合は拒否します
    next = request.GET.get('next','')
    if not user.profile.enable_two_factor_authentication and user.is_active and user.profile.check_auth_token(usertoken, token): # 認証トークンを確認してください
        auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # 彼らがまだログインしていない場合、ユーザーにログインします
        user.profile.mfa_expires = timezone.now() + datetime.timedelta(minutes=settings.LOGIN_VALID_MINUTES) # マルチファクター認証の有効期限を設定します
        user.profile.save()
        return HttpResponseRedirect(next if next != '' else reverse('landing:landing')) # ユーザーを次のページにリダイレクトします
    if not user.profile.mfa_enabled: # MFAが有効になっているかどうかを確認してください
        if not check_verification_time(user, token): # 時間を確認してください
            user.profile.mfa_enabled = False # 電話番号をクリアします
            user.profile.enable_two_factor_authentication = True # MFAを有効にします
            user.profile.phone_number = '+1' # 電話番号を無効にします
            user.profile.save() # プロファイルを保存します
            auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # MFAが有効になっていない場合はユーザーにログインします
            messages.warning(request, 'Please enter a valid phone number and verify it with a code.')
            return redirect(reverse('users:mfa_onboarding'))
    if request.method == 'POST' and not fraud_detect(request, True): # リクエストがPOSTリクエストの場合
        form = TfaForm(request.POST) # フォームをインスタンス化します
        code = str(form.data.get('code', None)) # コードを取得します
        if code and code != '' and code != None: # 空でないことを確認してください
            token_validated = user.profile.check_auth_token(usertoken) # 認証トークンを確認してください
            p = user.profile
            is_verified = check_verification_code(user, token, code) # コードを確認してください
            p.mfa_authenticated = is_verified
            if token_validated: # すべてがあれば
                if is_verified: # 順番です
                    user.profile.mfa_enabled = True # MFAを有効にする(まだ有効になっていない場合)
                    user.profile.save()
                    auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # ユーザーにログインします
                    face = user.faces.filter(session_key=None).last() 
                    p.mfa_expires = timezone.now() + datetime.timedelta(minutes=settings.LOGIN_VALID_MINUTES)
                    p.save()
                    messages.success(request, 'You have been authenticated. Welcome.')
                    qs = '?'
                    for key, value in request.GET.items(): # 次のパラメーターのクエリストリングを構築する(存在する場合)
                        qs = qs + key + '=' + value + '&'
                    if next != '' and not (next.startswith('/accounts/logout/') or  next.startswith('/accounts/login/') or next.startswith('/admin/login/') or next.startswith('/accounts/register/')):
                        return HttpResponseRedirect(next) # リダイレクト
                    elif next.startswith('/accounts/logout/') or next.startswith('/accounts/login/') or next.startswith('/accounts/register/'):
                        return redirect(reverse('/'))
                    elif request.META.get('HTTP_REFERER', '/').startswith('/accounts/login/'):
                        return redirect(reverse('/'))
                    elif not next:
                        return redirect(reverse('/'))
                    else:
                        return HttpResponseRedirect(reverse('verify:age') + '?next=' + request.META.get('HTTP_REFERER', '/'))
                else:
                    messages.warning(request, 'The code you entered was not recognized. Please try again.')
            elif not token_validated: # トークンが無効だった場合
                messages.warning(request, 'The URL token has expired or was not recognized. Please try again.')
                logout(request)
                return redirect(reverse('users:login'))
            if p.mfa_attempts > 3: # 試みが多すぎる場合
                messages.warning(request, 'You have entered the incorrect code more than 3 times. please send yourself a new code.')
                p.verification_code = None
                p.save()
        elif user.profile.can_send_mfa < timezone.now():
            user.profile.mfa_attempts = 0
            user.profile.can_send_mfa = timezone.now() + datetime.timedelta(minutes=2)
            user.profile.save()
            if form.data.get('send_email', False): # 電子メール(またはテキスト)を送信する
                send_mfa_verification_email(user, token)
            else:
                send_verification_text(user, token)
            messages.success(request, "Please enter the code sent to your phone number or email. The code will expire in 3 minutes.")
        elif user.profile.can_send_mfa < timezone.now() + datetime.timedelta(seconds=115):
            messages.warning(request, 'You are sending too many two factor authentication codes. Wait a few minutes before sending another code.')
    form = TfaForm()
    hide_logo = None
    if user.profile.hide_logo:
        hide_logo = True
    if request.user.is_authenticated: return redirect(reverse('/'))
    # フォームをレンダリングします(Get Requests用)
    return render(request, 'users/mfa.html', {'title': 'Enter Code', 'form': form, 'xsmall': True, 'user': user, 'hide_logo': hide_logo, 'accl_logout': user.profile.shake_to_logout, 'preload': False, 'autofocus': request.method == 'POST'})
このコードを追加するときは、電子メールを送信するために関数をインポートしてください。ファイルの上部で、ユーザーは(他のインポート付き)を表示します。

from .mfa import send_verification_email as send_mfa_verification_email
これで、これが機能する前にその関数を書く必要があります。送信メール機能を拡張し、検証コードを使用してユーザーにメールを送信するだけです。

nano users/mfa.py

def send_verification_email(user, token):
    length = user.profile.verification_code_length
    code = random.randint(get_num_length(1, length), get_num_length(9, length));
    token.token = code
    token.expires = timezone.now() + datetime.timedelta(minutes=settings.AUTH_VALID_MINUTES)
    token.save()
    send_html_email(user, "Your verification code for {} is {}".format(settings.SITE_NAME, str(code)), "<p>Dear {},</p><p>Your verification code for {} is {}. Thank you for using this code to secure your account.</p><h2>{}</h2><p>Sincerely, {}</p>".format(user.profile.name, settings.SITE_NAME, str(code), str(code), settings.SITE_NAME))
したがって、これはすべてうまく機能します。現在、電話番号または電子メールに依存する多因子認証システムがあります。ただし、削除する方法も必要です。これらは、スパマー、ロボット、または私たちの仕事を意味しない人である可能性があります。私のウェブサイトでユーザーを監視するためのビューを見てください:

# 金額
from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import user_passes_test
from .tests import is_superuser_or_vendor # このテストを作成する必要があります

@login_required
@user_passes_test(is_superuser_or_vendor)
def users(request):
    # ユーザーのリストを取得します
    new_today = User.objects.filter(is_active=True, date_joined__gte=timezone.now() - datetime.timedelta(hours=24)).count()
    new_this_month = User.objects.filter(is_active=True, date_joined__gte=timezone.now() - datetime.timedelta(hours=24*30)).count()
    subscribers = User.objects.filter(is_active=True, profile__subscribed=True).count()
    return render(request, 'users/users.html', { # テンプレートでユーザーを返します
        'title': 'All Accounts',
        'users': User.objects.all(),
        'new_today': new_today,
        'new_this_month': new_this_month,
        'subscribers': subscribers
    })
このコードはテストを使用していることに注意してください。このテストをtests.pyファイルで宣言してインポートする必要があります。ユーザー/tests.pyの編集、テストを作成しましょう。

def is_superuser_or_vendor(user):
    return user.profile.vendor or user.is_superuser
これは、users/users.htmlテンプレートと組み合わせて、次のようになります。
 
{% extends 'base.html' %}
{% load app_filters %}
{% block content %}
<h1>All Registered Visitors</h1>
<p>{{ new_today|nts|capitalize }} new today, {{ new_this_month|nts }} new this month, {{ subscribers|nts }} subscribers, {{ users.count|nts }} total.</p>
<hr style="color: red;">
{% for user in users %}
{% include 'users/_user.html' %}
<hr style="color: blue;">
{% endfor %}
{% endblock %}
 
テンプレートには別のテンプレート、ユーザー/_user.htmlが含まれていることに注意してください。サブテンプレートを持ち、拡張機能を使用しないテンプレートを使用する場合、テンプレートを区別するために、ファイルの名前の前にアンダースコア(_)を追加することをお勧めします。 これは多くのジンジャであり、これらの変数のすべてが定義されているわけではないことに注意してください。しかし、これが私のコードの外観です。
 
{% load app_filters %}
<div>
<img src="{{ user.profile.get_image_url }}" alt="@{{ user.profile.name }}'s profile photo" width="120" height="120" align="left" style="margin-top:5px; margin-right:10px; margin-bottom:10px; border-radius: 50%;"/>
    <div class="article-metadata">
      <p class="mr-2">@{{ user.username }} - {{ user.profile.name }} ({{ user.profile.preferred_name }})</p>
      <small class="text-muted">Last seen {{ user.profile.last_seen|date:"F d, Y" }} {{ user.profile.last_seen|time:"H:i" }}</small>
      <small class="text-muted">Joined on {{ user.profile.date_joined|date:"F d, Y" }} {{ user.profile.date_joined|time:"H:i" }}</small>
      <small>{{ user.email }}</small>
      {% if user.profile.phone_number %}<small><i class="bi bi-phone-fill"></i>{{ user.profile.phone_number }}</small>{% endif %}
      {% if user.verifications.last %}
      <small>'{{ user.verifications.last.full_name }}'</small>
      <small><i class="bi bi-123"></i> {{ user.verifications.last.document_number }}</small>
      <small><i class="bi bi-calendar-heart-fill"></i> {{ user.verifications.last.birthdate }}</small>
      <a href="{{ user|document_front }}" class="btn btn-sm btn-outline-primary" title="ID front"><i class="bi bi-person-badge-fill"></i> ID front</a>
      <a href="{{ user|document_back }}" class="btn btn-sm btn-outline-primary" title="ID back"><i class="bi bi-upc-scan"></i> ID back</a>
      {% endif %}
      <small># {{user.id}} </small>
      <small>{% if user.profile.subscribed %}Subscribed{% else %}Not subscribed{% endif %}</small>
    </div>
    {%if not user.is_superuser %}
    <div style="float: right;">{% include 'users/toggle_active.html' %}</div>
    {% endif %}
    {% autoescape off %}    
    <p class="article-content">{{ user.bio }}</p>
    {% endautoescape %}
    <hr>
    <p>{% if user.profile.identity_verified %}Verified user.{% else %}Unverified user.{% endif %} Verifications: {{ user.verifications.count|nts }}</p>
 
また、別のサブテンプレート、toggle_active.htmlも必要です。このテンプレートは、ユーザーがアクティブであるかどうかを切り替えることができるフォームである必要があります。
 
<form style="display: inline-block;" action="{% url 'users:toggle-user-active' user.id %}" method="POST" id="publishForm">
<button class="btn btn-sm btn-outline-danger" type="submit">{% if user.is_active %}<i class="bi bi-eye-fill"></i>{% else %}<i class="bi bi-eye-slash-fill"></i>{% endif %}</button>
</form>
 
また、ユーザーアクティビティと適切なURLパターンを切り替えるビューを追加する必要があります。私たちがそれに取り組んでいる間、それが必要な場合にユーザーを削除するビューを追加しましょう。

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
@login_required
@user_passes_test(is_superuser_or_vendor)
def toggle_user_active(request, pk):
    user = User.objects.get(id=pk)
    if request.method == 'POST':
        user.is_active = not user.is_active
        user.save()
    return HttpResponse('<i class="bi bi-eye-fill"></i>' if user.is_active else '<i class="bi bi-eye-slash-fill"></i>')


# 金額
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.views.generic import DeleteView

class UserDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
    model = User
    success_url = '/' # 成功URLのリダイレクト
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        return context

    def test_func(self): # ユーザーがスーパーユーザーであり、削除する許可があるかどうかをテストします
        user = self.get_object()
        if self.request.user != user and self.request.user.is_superuser:
            return True
        return False
これは必要に応じて実用的ですが、ほとんどの場合、ユーザーを削除する必要はありませんが、却下する必要がある場合は、サイトにアクセスするユーザーの可視性を切り替えることができます。 追加したURLパターンは、このように見えます。 nanoを使用して、ユーザー/urls.pyを編集して、これらの行を追加します。

nano users/urls.py
行は、「]」の前に、「[」[「」の後に、ユーザービューのパスのリストに入力する必要があります。

# …
    path('user/<int:pk>/delete/', UserDeleteView.as_view(template_name='blog/user_confirm_delete.html'), name='delete-user'),
    path('user/<int:pk>/active/', views.toggle_user_active, name='toggle-user-active'),
# …
次に、サイトをバックアップして、作業を続けるWebサーバーにダウンロードできるようにしてください。コマンドラインから、

sudo backup
今、私たちのサイトはバックアップされています。 そのため、いくつかの便利な機能があります。しかし、ここの全体像はどうですか?このコードはまだインターネットからアクセスできないため、メールサーバーはまだありません。また、特権ユーザーを認証するための安全なプロトコルとともに、サイトを探索するための包括的な検証プロセスとスムーズなレイアウトを含めるためにアプリを拡張する必要があります。 。 これらすべてに到達します。今のところ最も重要なことは、このコードをオンラインで取得することです。これは、Ubuntuサーバーでのほんの数行のbashでできます。ただし、自宅にサーバーとポートを開くことができるビジネスインターネットサブスクリプションがない限り、このためにサーバーをレンタルする必要があります。私は個人的に私のアパートにインストールされているHP Z440でウェブサイトを実行していますが、通常、仮想プライベートサーバー(VPS)をレ​​ンタルするための基本的なニーズがはるかに安いです。 私たちが今実行しているコードは比較的薄く、私たちがいる前に維持および改善する必要があることに留意してください製品を構築するために必要なものを使用する準備ができました。インターネットで何をしているかに注意してください。このサイトをLinuxサーバーでWebに公開している場合は、Webサイトとの不要なやり取りをブロックする計画があります。これは最初は問題にならないでしょうが、機械学習、人工知能、コンピュータービジョンなど、これと戦うためのさまざまなソリューションを検討します。問題が発生したら、このテキストをさらに検討して、解決策を確認してください。 VPSを借りるという点では、行くことができる場所がたくさんあります。 Google Cloudには、VPSサーバー、Ionos、Kamatera、Amazon AWS、およびより多くのプロバイダーが私たちのニーズに合ったクラウドサーバーソリューションを提供しています。 フォームをクリックして、開始する計画を選択する必要があります。プロバイダーと一緒に基本プランを使用することはできますが、プロバイダーがポートメールサーバーポートを開いて電子メールを送信できることを確認してください(これはポート587とポート25である必要があります)、一部のプロバイダーはこれらのポートをブロックします。これまでのところ、私は持っていますIonosとKamateraのESTの経験は、どちらも無制限の電子メールを送信することができ、価格はかなり安いです。 SSHまたはSecure Shellというプロトコルを介して新しいサーバーに接続します。これにより、パーソナルコンピューターからパーソナルコンピューターとまったく同じようにサーバーとリモートでインターフェイスできます。サーバーをセットアップすると、ホスティングプロバイダーはSSHキーを追加するように依頼する可能性があります。または、ユーザー名とパスワードが表示されます。 SSHキーは、コマンドラインからサーバーにログインしてコードを編集する方法です。以下のSSH-KeyGenオプションを使用して、SSHを生成します

ssh-keygen
ファイルを保存して、必要に応じて上書きする必要がある場合は、SSHキーをまだ回転させていない場合は良いことです。これで、次のコマンドを使用してSSHキーを表示できます。リモートサーバーにコピーして、使用して認証できるようにする必要があります。

cat ~/.ssh/id_rsa.pub
そのコマンドを入力するときにSSHキーを見ることができなかった場合(「SSH-RSA AAA」から始まる数字と文字の長い文字列)、RSAキーを生成してみてください(より安全なので、使用することをお勧めします。)次のコードは、4096ビットRSA SSHキーを生成します。

ssh-keygen -t rsa -b 4096
Ubuntuを実行しているVPSを作成しますが、これを行う予定です。プロバイダーのWebサイト(kamatera.com、ionos.comなど)のフォームをクリックしてVPSを作成したら、ログインする必要があります。これを行うには、IPアドレス(アドレス)でSSHコマンドを使用します。 xx.xx.xx.xxのように見えます)。また、作成したサーバー上のデフォルトのユーザー名、たとえばubuntuに敏感である必要があります。

ssh ubuntu@XX.XX.XX.XX
パスワードを要求される場合があります。パスワードを求められている場合は、入力してください。デフォルトのユーザー名は使用しません。まず、新しいユーザーを作成してSSHキーをアカウントに追加してください。 まず、SSHの使用方法をサーバーに伝える新しいSSHD_CONFIGファイルを追加します。

nano sshd_config

# これは、SSHDサーバーシステム全体の構成ファイルです。  見る
# SSHD_CONFIG(5)詳細については。

# このSSHDは、path =/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/gamesでコンパイルされました

# デフォルトのsshd_configのオプションに使用される戦略
# opensshは、デフォルトの値でオプションを指定することです。
# 可能ですが、彼らにコメントしたままにしておきます。  メントなしのオプションはオーバーライドします
# デフォルト値。

# ポート22
# アドレスファミリー任意
# リストアドレス0.0.0.0
# アドレスを聞く::

# hostkey/etc/ssh/ssh_host_rsa_key
# hostkey/etc/ssh/ssh_host_ecdsa_key
# hostkey/etc/ssh/ssh_host_ed25519_key

# 暗号とキーイング
# rekeylimitデフォルトなし

# ロギング
# Syslogfacility Auth
# loglevel情報

# 認証:

# logringraceTime 2m
# permitrootloginはパスワードを禁止します
# StrictModesはい
# Maxauthries 6
# 最大10

PubkeyAuthentication yes

# .ssh/authorized_keys2が将来デフォルトで無視されることを期待してください。
AuthorizedKeysFile	.ssh/authorized_keys .ssh/authorized_keys2

# 認定principalsfileなし

# 認定KeysCommandなし
# authizedkeyscommanduser誰も

# これを機能させるには、/etc/sssh/ssh_known_hostsのホストキーも必要です
# hostbasedAuthentication no
# 〜/.ssh/nown_hostsを信頼していない場合は、はいに変更します
# hostbasedAuthentication
# IngroreUserknownhosts no
# ユーザーの〜/.Rhostsおよび〜/.shostsファイルを読んではいけません
# IgnorerHostsはい

# Tunneled Clear Textパスワードを無効にするには、ここでNOに変更してください!
PasswordAuthentication no
# ammitemptypasswords no

# offery-responseパスワードを有効にするには、はいに変更します(問題に注意してください
# いくつかのPAMモジュールとスレッド)
KbdInteractiveAuthentication no

# Kerberosオプション
# Kerberosauthentication no
# kerberosorlocalpasswdはい
# kerberosticketcleanupはい
# Kerberoscotted Rod no

# GSSAPIオプション
# gssapiauthentication no
# gssapicleanupcredentialsはい
# gssapistrictacceptorcheckはい
# gssapikeyexchange no

# これを「はい」に設定して、PAM認証、アカウント処理を有効にします。
# およびセッション処理。これが有効になっている場合、PAM認証は行われます
# KBDINTERACTIVEAUTHENTICIATIONを介して許可されます
# PasswordAuthentication。  PAM構成に応じて、
# KBDINTERACTIVEAUTHENTICATIONによるPAM認証は、バイパスされる場合があります
# 「パスワードのないPermitrootlogin」の設定。
# PAMアカウントとセッションチェックが必要な場合は、
# PAM認証は、これを有効にしますが、PasswordAuthenticationを設定します
# および「いいえ」へのkbdinteractiveauthentication。
UsePAM yes

# AlowAgentForwardingはい
# Alowtcpforwardingはい
# ゲートウェイポート番号
X11Forwarding yes
# x11displayoffset 10
# x11uselocalhostはい
# 許可はい
PrintMotd no
# printlastlogはい
# tcpkeepaliveはい
# 許合性
# 圧縮遅延
# クライアントアラブインターバル0
# ClientAliveCountMax 3
# usedns in
# pidfile /run/sshd.pid
# Maxstartups 10:30:100
# Pemittunl no
# Chrootdirectoryなし
# バージョン補遺なし

# デフォルトのバナーパスはありません
Banner /etc/banner

# クライアントがロケール環境変数を渡すことを許可します
AcceptEnv LANG LC_*

# サブシステムなしのデフォルトをオーバーライドします
Subsystem	sftp	/usr/lib/openssh/sftp-server

# ユーザーごとのオーバーライド設定の例
# ユーザーANONCVSを一致させます
# x11forwarding no
# Allowtcpforwarding no
# 許可
# ForceCommand CVSサーバー
PermitRootLogin no
ファイルを保存するには、ctrl+xおよびyを覚えておいてください。次に、Initialize(すべてユーザーのデフォルトのホームディレクトリにあるすべて)という基本的なスクリプトを書きましょう。

nano initialize
これらの行をファイルに追加し、置き換えますSSHキーを使用して、CATを使用して見つかりました。 (.ssh/id_rsa.pub)

# ! / bin / bash
sudo apt install -y nano git openssh-server
sudo cp sshd_config /etc/ssh/sshd_config
sudo service ssh restart
sudo service sshd restart
echo "/root/.ssh/id_rsa" | sudo su root -c "ssh-keygen -t rsa -N ''"
echo "root ssh key:"
sudo su root -c "cat /root/.ssh/id_rsa.pub"
sudo adduser --disabled-password --gecos "" team
sudo passwd -d team
sudo usermod -aG sudo team
echo "/home/team/.ssh/id_rsa" | su team -c "ssh-keygen -t rsa -N ''"
cat /home/team/.ssh/id_rsa.pub >> /home/team/.ssh/authorized_keys
echo '<key here>' >> /home/team/.ssh/authorized_keys
echo "team ssh key:"
cat /home/team/.ssh/id_rsa.pub
このファイルを紹介するには、行ごとにスタートしましょう。最初の行は、これがバッシュスクリプトであることをコンパイラに伝えます。次に、依存関係をインストールし、sshd_configを正しいディレクトリにコピーし、sshの再起動、rootのsshキーの生成、ユーザー「チーム」を追加することができます(これに好きな名前を選択できます。今)。また、Sudoグループにチームを追加し、SSHキーを生成し、承認されたキーとそれらのキーにもキーを追加し、キーを印刷します。この新しいユーザーは、サイトへのログイン方法です。 新しい端末で、先に進んでサーバーを再度開きます。

ssh team@XX.XX.XX.XX
SSHキーがあるので、今回はパスワードを必要としません。また、サイトを安全に保つために、パスワードでログインを無効にしました。 これで、このサーバーは情報がなく、完全に空白に起動します。 Gitからプロジェクトをクローニングして、リモートマシンでダウンロードして実行できるようにしましょう。 SSHに接続されたリモートサーバーで、最初にSSHキーを印刷します。

cat ~/.ssh/id_rsa.pub
次に、このキーをGitリポジトリをセットアップするために前に行ったように、GIT設定に貼り付けます。これで、プロジェクトをサーバーに直接クローンすることができます。最初にプロジェクトをローカルでバックアップしていることを確認して、Gitサーバー上にダウンロードしてください。

git clone git://github.com/you/yourproject.git
完璧。これで、すべてのファイルがここにあります。 LSでそれらを見ることができます

ls
それでは、サーバーのセットアップを始めましょう。まず、プロジェクトディレクトリをプロジェクトに使用するシンプルで記憶に残る名前にコピーします。

cp -r yourproject whatyoucalledit
ここで、「Whatyoucalledit」はあなたのプロジェクトの新しい名前です。次に、サーバーをセットアップするには、基本的なユーティリティを構築する必要があります。このユーティリティを保存し、将来使用します。このユーティリティを構築するには、ユーザーバイナリを作成して、スクリプトの編集方法を定義します。 BASHを使用して、編集/usr/bin/ascript

sudo nano /usr/bin/ascript
ファイルを編集する権限があるように、そこにsudoを使用してください。ファイルに、これらの行を追加します。

# ! / bin / bash
if [ ! -f /usr/bin/$1 ]; then
    sudo touch /usr/bin/$1
    echo "# ! / bin / bash ">> / bin / $ 1
    sudo chmod a+x /usr/bin/$1
    sudo nano /usr/bin/$1
    echo $1 | sudo tee -a /etc/ascripts
else
    sudo chmod a+x /usr/bin/$1
    sudo nano /usr/bin/$1
fi
このスクリプトは、スクリプト名を1ドルとすることを忘れないでください。最初に、ファイルが存在するかどうかを確認するか、その他の方法で作成し、最初の行を追加してスクリプトがバッシュであると宣言し、その権限を変更し、編集し、その名前を /etc /ascriptsに追加して、スクリプトの名前を保存できるようにします。作成しています。ファイルが既に存在する場合は、権限を変更して編集するだけです。ファイルを保存すると、次にその権限を変更します。このスクリプトを使用している限り、それをもう一度行う必要はありません。

sudo chmod a+x /usr/bin/ascript
完璧。次に、セットアップというスクリプトを作成しましょう。まず、あなたを圧倒するのではなく、私のセットアップスクリプトがどのように見えるかを見てみましょう。私たちはあなたのプロジェクトでこのスクリプトがどのように見えるべきかを説明します、あなたは私のスクリプト内のすべてを最初から必要とすることはありません。

# ! / bin / bash
SECONDS=0
PYTHON_VERSION=3.12
echo "femmebabe installer initialized."
# sudo chmod a+x scripts/usersetup
# ./scripts/usersetup
# ssh-keyen
# プロジェクトディレクトリ
DIR="/home/team/femmebabe"
USER="team"
# ログコマンド
echo "Logging commands"
sudo cp log/commands.log /var/log/commands.log
sudo chmod -R a+w /var/log
sudo chown -R :syslog /var/log
echo $'alias venv="source /home/team/femmebabe/venv/bin/activate"' | sudo tee -a /home/team/.profile
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a /etc/bashrc
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a "/home/team/.bashrc"
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a /root/.bashrc
echo "source /etc/bashrc" | sudo tee -a /home/team/.profile
echo "/var/log/commands.log" | sudo tee -a /etc/logrotate.d/syslog
echo "local6.*    /var/log/commands.log" | sudo tee -a "/etc/rsyslog.d/bash.conf"
sudo service rsyslog restart
# nano config
echo "set tabsize 4" >> .nanorc
echo "set tabstospaces" >> .nanorc
# git config
echo "Git configuration"
sudo git config --global user.email "jasper.camber.holton@gmail.com" && sudo git config --global user.name "Jasper Holton"
git config --global user.email "jasper.camber.holton@gmail.com"
git config --global user.name "Jasper Holton"
git config --global --add safe.directory $"$DIR"
sudo ssh-keyscan -t rsa gitlab.com | sudo tee -a /root/.ssh/known_hosts
sudo ssh-keyscan -t rsa github.com | sudo tee -a /root/.ssh/known_hosts
echo "Mounting setup"
sudo mount -o remount,size=16G,exec /tmp
# 更新してインストールします
echo "Update and install packages"
sudo apt update && sudo NEEDRESTART_MODE=a apt upgrade -y
sudo apt purge postgresql-client-14 postgresql-client-common postgresql-common postgresql-contrib postgresql -y
echo "postfix postfix/mailname string femmebabe.com" | sudo debconf-set-selections
echo "postfix postfix/main_mailer_type string 'Internet Site'" | sudo debconf-set-selections
sudo NEEDRESTART_MODE=a DEBIAN_FRONTEND=noninteractive apt install -y postfix
sudo NEEDRESTART_MODE=a apt install -y rkhunter clamav-daemon libx264-dev ffmpeg libapache2-mod-wsgi-py3 apache2 cmake python-is-python3 python3-venv python3-pip python3-django expect tesseract-ocr openjdk-8-jdk redis-server libopencv-dev python3-opencv python3-dev libsasl2-dev opendkim opendkim-tools dovecot-core dovecot-pop3d dovecot-imapd auditd procmail libpq-dev postgresql postgresql-contrib libheif-dev snapd git software-properties-common certbot python3-certbot-apache
echo "-a exit,always -F arch=b64 -F euid=0 -S execve" | sudo tee -a /etc/audit/audit.rules
echo "-a exit,always -F arch=b32 -F euid=0 -S execve" | sudo tee -a /etc/audit/audit.rules
# クラマブアンチウイルスを有効にします
echo "Starting antivirus"
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# ホスト名を設定します
echo "127.0.0.1 femmebabe" | sudo tee -a /etc/hosts
sudo hostnamectl set-hostname localhost
# Postgresをセットアップします
echo "Postgres setup"
sudo -u postgres psql -U postgres -c "DROP DATABASE database;"
sudo -u postgres psql -U postgres -c "CREATE DATABASE database;"
sudo -u postgres psql -U postgres -c "CREATE USER django WITH PASSWORD 'password';"
sudo -u postgres psql -U postgres -c "ALTER ROLE django SET client_encoding TO 'utf8';"
sudo -u postgres psql -U postgres -c "ALTER ROLE django SET default_transaction_isolation TO 'read committed';"
sudo -u postgres psql -U postgres -c "ALTER ROLE django SET timezone TO 'UTC';"
sudo -u postgres psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE database TO django;"
# バックアップデータベースのセットアップ
echo "Building database from backup, this may take a while."
cat db.json.?? > db.json
echo "Configuring firewall"
sudo ufw default allow outgoing
sudo ufw default deny incoming
sudo ufw allow 22
sudo ufw allow http
sudo ufw allow https
sudo ufw allow 'Postfix'
sudo ufw allow 'Postfix SMTPS'
sudo ufw allow 'Postfix Submission'
sudo ufw allow 'Dovecot POP3'
sudo ufw allow 'Dovecot Secure POP3'
sudo ufw allow 110/tcp
sudo ufw allow 25/tcp
echo "y" | sudo ufw enable
# 無効化されたiPatables
echo "Configuring firewall"
sudo iptables -P INPUT ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -F
sudo iptables-save
# BitDefenderをインストールします
cd $DIR
echo "Runnning BitDefender antivirus installer"
wget https://cloud.gravityzone.bitdefender.com/Packages/NIX/0/7aTSsy/setup_downloader.tar
mkdir bitdefender
tar -xf setup_downloader.tar -C bitdefender
sudo rm setup_downloader.tar
sed -i -e 's/{LOGINPASSWD/z&A*3BPd_qBGUMs/g' bitdefender/installer
sudo chmod a+x bitdefender/installer
sudo ./bitdefender/installer
# ポストフィックスをセットアップします
cd $DIR
echo "Mail services configuration"
sudo cp /etc/postfix/main.cf /etc/postfix/main.cf.backup
sudo cp config/etc_postfix_main.cf /etc/postfix/main.cf
sudo cp config/etc_postfix_master.cf /etc/postfix/master.cf
sudo cp config/etc_default_opendkim /etc/default/opendkim
sudo cp config/etc_dovecot_conf.d_10-auth.conf /etc/dovecot/conf.d/10-auth.conf
sudo cp config/etc_dovecot_conf.d_10-master.conf /etc/dovecot/conf.d/10-master.conf
sudo cp config/etc_dovecot_dovecot.conf /etc/dovecot/dovecot.conf
sudo cp config/etc_dovecot_passwd /etc/dovecot/passwd
sudo cp config/etc_opendkim.conf /etc/opendkim.conf
sudo cp config/etc_default_opendkim /etc/default/opendkim
sudo adduser postfix opendkim
sudo mkdir /etc/opendkim
sudo mkdir /etc/opendkim/keys
sudo mkdir /etc/opendkim/keys/femmebabe.com
sudo mkdir /var/spool/postfix/opendkim
sudo echo "*@femmebabe.com     sendonly._domainkey.femmebabe.com" | sudo tee -a /etc/opendkim/signing.table
sudo echo "sendonly._domainkey.femmebabe.com    femmebabe.com:sendonly:/etc/opendkim/keys/femmebabe.com/sendonly.private" | sudo tee -a /etc/opendkim/key.table
sudo echo "127.0.0.1" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "localhost" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "*.femmebabe.com" | sudo tee -a /etc/opendkim/trusted.hosts
sudo chown -R opendkim:opendkim /etc/opendkim
sudo opendkim-genkey -b 2048 -d femmebabe.com -D /etc/opendkim/keys/femmebabe.com -s sendonly -v
sudo chmod go-rw /etc/opendkim/keys
sudo chown opendkim:opendkim /etc/opendkim/keys/femmebabe.com/sendonly.private
sudo chown opendkim:postfix /var/spool/postfix/opendkim
cd $DIR
sudo cp mailbox/* /var/mail/
sudo chown :users /var/mail/*
sudo chmod -R a+rwx /var/mail/*
sudo systemctl restart opendkim postfix dovecot
# 監督を作成します
cd $DIR
mkdir media/audio
mkdir media/audio/fingerprints
mkdir media/security
mkdir media/secure
mkdir media/secure/media
mkdir media/secure/video
mkdir media/secure/profile
mkdir media/secure/face
mkdir media/images
mkdir media/live
mkdir media/live/files
mkdir media/live/stills
mkdir media/files
mkdir temp
mkdir temp/data
mkdir temp/gfpgan
mkdir mail/inbox
mkdir mailbox
# Setup Virtualenv
cd $DIR
echo "Creating virtual environment"
python -m venv venv
source venv/bin/activate
# 依存関係を取得して構築します
echo "Getting and building dependencies, this may take a whike"
cd $DIR
git clone https://github.com/sukhitashvili/violence-detection.git
cp config/vd-requirements.txt violence-detection/requirements.txt
cp config/vd-model.py violence-detection/model.py
cd violence-detection
pip3 install -r requirements.txt
cd $DIR
wget https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.3.pth -P experiments/pretrained_models
git clone https://github.com/TencentARC/GFPGAN.git
git clone https://github.com/davisking/dlib.git
cd dlib
mkdir build; cd build; cmake ..; cmake --build .
cd ..
source venv/bin/activate
python setup.py install
cd $DIR
source venv/bin/activate
cd $DIR/GFPGAN/
echo "Installing python dependencies"
pip install basicsr
pip install facexlib
pip install -r requirements.txt
python setup.py develop
pip install realesrgan
cd $DIR
sudo chown -R team:users gfpgan
echo "Installing ta-lib"
wget https://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz
tar xvzf ta-lib-0.4.0-src.tar.gz
sudo rm ta-lib-*
cd ta-lib
sudo ./configure
sudo make
sudo make install
# ファイアウォールルールを設定します
cd $DIR
# PYPI依存関係をインストールします
echo "Installing remaining python dependencies (this may take a while)"
sudo systemctl mask tmp.mount
cd $DIR
source venv/bin/activate
pip3 install -U "celery[redis]"
pip3 install -r requirements.txt --use-deprecated=legacy-resolver --use-pep517
pip3 install --upgrade opencv-python # == 4.5.4.60
pip3 install --upgrade opencv-contrib-python # == 4.5.4.60
# PIPインストールopencv-python == 4.5.5.64
# PIPインストールopencv-contrib-python == 4.5.5.64
pip3 install --upgrade opencv-python-headless
pip3 uninstall channels
pip3 uninstall daphne
pip3 install channels["daphne"]
pip3 install Pillow==9.5.0
pip3 install librosa
pip3 install -U 'Twisted[tls,http2]'
pip3 install --upgrade certifi requests urllib3 numpy oauthlib twisted pyjwt sqlparse cryptography astral webauthn docbarcodes pdf417 deepface --no-cache-dir
pip3 install tensorflow==2.15.1
# certbotをインストールします
echo "Installing certificates"
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo snap install redis
sudo systemctl enable apache2
sudo systemctl start apache2
# certbotを実行します
sudo certbot --apache --non-interactive --agree-tos --domains femmebabe.com --email jasper.camber.holton@gmail.com
# メールサーバーをリロードします
sudo systemctl restart opendkim postfix dovecot
# 証明書をコピーします
# sudo cp /etc/letsencrypt/live/femmebabe.com/privkey.pem privkey.pem
# sudo cp /etc/lettesencrypt/live/femmebabe.com/cert.pem cert.pem
# パッチ
cp scripts/content.py $"/home/team/femmebabe/venv/lib/python${PYTHON_VERSION}/site-packages/pyxb/binding/content.py"
cp scripts/pwa_webpush_forms.py $"/home/team/femmebabe/venv/lib/python${PYTHON_VERSION}/site-packages/pwa_webpush/forms.py"
cp scripts/webauth_views.py $"/home/team/femmebabe/venv/lib/python${PYTHON_VERSION}/site-packages/webauth/views.py"
cp scripts/json.py $"venv/lib/python${PYTHON_VERSION}/site-packages/django/core/serializers/json.py"
# ユーザー設定を設定します
sudo gpasswd -a www-data users
# 設定権限
echo "Setting permissions"
sudo chown -R team:users cache/
sudo chmod a+rwx -R cache/
# sudo chown -rチーム:ユーザー/var/run/
# sudo chownルート:root/run/sudo/ts -r
sudo chown -R redis:redis /var/lib/redis
sudo chown -R redis:redis /var/log/redis
sudo chmod -R u+rwX,g+rwX,u+rx /var/log/redis
sudo chmod +r /etc/redis/redis.conf
sudo chown -R team:users /var/log/
sudo chown -R :users .././
sudo chmod -R g+rwX ./
sudo chmod -R g+rX .././
sudo chmod -R g-rwX ../.ssh
sudo chmod 774 ./
# sudo chmod 664 db.sqlite3
# sudo chown www-data:ユーザーdb.sqlite3
sudo chown -R www-data:www-data media/
sudo chown www-data:users ./
sudo chown -R team:users media/
sudo chown -R team:users ./
sudo chown -R team:users ./gfpgan/
sudo chown -R team:users ./temp/
sudo chmod a+r team /var/mail/$USER
# 設定をコピーしてアクセス許可を設定します
echo "Configuring remaining services"
sudo cp config/apis.json /etc/apis.json
sudo cp config/config.json /etc/config.json
sudo cp config/femmebabe-le-ssl.conf /etc/apache2/sites-available/femmebabe-le-ssl.conf
sudo cp config/etc_dovecot_passwd /etc/dovecot/passwd
sudo cp config/etc_init.d_celery /etc/init.d/celery
sudo cp config/etc_init.d_celerybeat /etc/init.d/celerybeat
sudo cp config/etc_default_celerybeat /etc/default/celerybeat
sudo cp config/etc_default_celery /etc/default/celery
sudo cp config/etc_systemd_system_daphne.service /etc/systemd/system/daphne.service
sudo cp config/etc_systemd_system_celery.service /etc/systemd/system/celery.service
sudo cp config/etc_systemd_system_celerybeat.service /etc/systemd/system/celerybeat.service
sudo chmod a+x /etc/init.d/celery
sudo chmod a+x /etc/init.d/celerybeat
# データベースのセットアップ
echo "Running migrations, this should be quick"
python manage.py makemigrations
python manage.py migrate --run-syncdb
echo "Loading data, this may take a while"
python manage.py loaddata db.json
echo "Setup crontab/sudoers configuration"
sudo crontab -l -u root | cat - config/crontab | sudo crontab -u root -
sudo sh -c "cat config/sudoers >> /etc/sudoers"
# PAM構成を注入し、故障したSSH構成を削除します
# sudo sed -i '' -e '$ d' /tc/pam.d/sshd
# sudo sed -i ''  - および$ d ' /etc /プロフィール
echo "session required pam_exec.so seteuid /home/team/femmebabe/pam.sh" | sudo tee -a /etc/pam.d/sshd
echo "session required pam_exec.so seteuid /home/team/femmebabe/logout.sh" | sudo tee -a /etc/pam.d/sshd
sudo chmod a+x pam.sh
sudo rm /etc/ssh/sshd_config.d/50-cloud-init.conf
# ビンスクリプトをコピーしてアクセス許可を設定します
echo "Copying scripts"
sudo cp scripts/reload /usr/bin/
sudo cp scripts/check /usr/bin/
sudo cp scripts/enagpu /usr/bin/
sudo cp scripts/disgpu /usr/bin/
sudo cp scripts/activate /usr/bin/
sudo cp scripts/backup /usr/bin/
sudo cp scripts/ascript /usr/bin/
sudo cp scripts/setup /usr/bin/
sudo cp scripts/addsetup /usr/bin/
sudo cp scripts/watchlogs /usr/bin/
sudo cp scripts/logs /usr/bin/
sudo cp scripts/cmds /usr/bin/
sudo cp scripts/setup /usr/bin/
sudo cp scripts/pushweb /usr/bin/
sudo cp scripts/purgecache /usr/bin/
sudo cp config/banner /etc/banner
cd /usr/bin/
sudo chmod a+x activate
sudo chmod a+x backup
sudo chmod a+x ascript
# サービスをリロードおよび有効にします
echo "Enabling services"
sudo systemctl daemon-reload
sudo systemctl enable daphne.service
sudo systemctl enable celery.service
sudo systemctl enable celerybeat.service
sudo systemctl enable clamav-daemon
sudo systemctl start daphne.service
sudo systemctl start celery.service
sudo systemctl start celerybeat.service
sudo systemctl start clamav-daemon
# Apacheモジュールを有効にします
echo "Enabling apache2"
sudo a2enmod rewrite
sudo a2enmod wsgi
sudo a2enmod headers
sudo a2enmod ssl
sudo a2enmod proxy
sudo a2enmod proxy_balancer
sudo a2enmod proxy_http
sudo a2enmod proxy_wstunnel
# sudo a2dismod mpm_event
# sudo a2dismod mpm_worker
# sudo a2enmod mpm_prefork
# デフォルトサイトを無効にします
sudo a2dissite 000-default
sudo a2dissite 000-default-le-ssl
# サイトを有効にします
sudo a2ensite femmebabe-le-ssl
# デーモンをリロードし、アパッチ、ポストフィックス、opendkimを再起動します
sudo systemctl daemon-reload
sudo systemctl restart apache2
sudo systemctl restart opendkim postfix
sudo systemctl start daphne
# 設定権限
sudo chown -R :www-data /var/www/
sudo chown -R :www-data /var/www/.deepface
# 構成を交換します
echo "Allocating swap, this may take a while"
sudo swapoff /swapfile
sudo rm /swapfile
sudo fallocate -l 8G /swapfile
sudo dd if=/dev/zero of=/swapfile bs=1024 count=8388608
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo "/swapfile swap swap defaults 0 0" | sudo tee -a /etc/fstab
sudo swapon --show
# INITキャプションエンジン
echo "Initializing routine caption"
/home/team/femmebabe/venv/bin/python /home/team/femmebabe/routine_caption.py
/home/team/femmebabe/venv/bin/python /home/team/femmebabe/setup_mail.py
# Gitをセットアップします
echo "Setting up git"
cd $DIR
sudo rm -r .git
git init --initial-branch=main
echo "Setting user password"
sudo usermod --password $(echo team | openssl passwd -1 -stdin) team
# ドメイン構成のIPv6とOpendKimを表示します
echo "COPY the below information to domain configuration."
hostname -I
ip a | grep inet
ip -6 addr | grep "scope link"
sudo cat /etc/opendkim/keys/femmebabe.com/sendonly.txt | tr -d '\n' | sed 's/\s//g' | sed 's/""//g' | awk -F'[)(]' '{print $2}'
# セットアップが完了しました
echo "Setup completed in"
wc -l scripts/setup
echo "lines of code."
echo "Total time:"
duration=$SECONDS
echo "$((duration / 60)) minutes and $((duration % 60)) seconds elapsed."
echo "TODO:"
echo "- COPY above IPv6 address to domain DNS configuration"
echo "- COPY domain key to domain DNS configuration"
echo "- ADD new git repository with git remote add originlab <repo>."
echo "- OPEN port 25"
echo "- INSTALL antivirus as per reccomendations"
echo "- TEST"
echo "If neccesary,"
echo "- DEBUG"
echo "- FIX setup and backup scripts"
echo "- Fix server"
echo ""
echo "Thank you for using the femmebabe installer. Have a great day!"
echo "Goodbye."
それはたくさんのセットアップです!要するに、このコードはコマンドを記録し、NANOとGITを構成し、ファイルをコピーし、Ubuntu APTパッケージ、Python依存関係をダウンロードしてインストールし、Postfixを構成し、PostgreSQL(データベースサーバー)を構成し、データベースをロードし、UFW(不整合のFireWall)を構成します。 iptablesを無効にし、ウイルス対策をダウンロードし、ディレクトリを作成し、クローン依存関係を作り、証明書をインストールし、サーバーをセットアップし、構成をインストールし、SEVERを開始して有効にし、スワップを割り当て、アクセス許可を設定し、IP、IPv6アドレス、OpenDKIMキーを印刷します。かなり簡単ですが、多くのコードのように見えます。依存関係がないため、セロリ、セロリビート、ダフネを使用していないため、これは多く必要ありませんが、とにかくいくつかをインストールして開始します。このコードにはドメインが数回宣言されていることに注意してください。 また、ドメイン名を購入する必要があります(これは年間少額の料金です)。ドメインを購入するためにSquarespaceをお勧めします。レイアウトは直感的で使いやすい。お好みのドメインは任意のドメインを購入できますが、この例ではdomain femmebabe.comを使用しています。ドメインを購入したら、Squarespace DNS構成パネルに移動し、IPアドレスでサーバーにドメインを指すレコードを追加します。このように見えるはずです: @ a xx.xx.xx.xx @ operatorをホストとして、つまり、このドメインとルートドメインの下のすべてのサブドメインを意味します。すべてサーバーにリダイレクトされます。宣言するレコードはもっとありますが、メールを送信する準備ができたら、これらに進むことができます。サーバーからメールを正常に送信できるようになるまでに数日かかる場合があります。設定しているDNSレコードは、伝播するのに時間がかかります。 とにかく、開始する必要がある唯一のレコードはAレコードです。そのため、プロジェクトに従って以下のスクリプトに記入して実行できます。 より小さなセットアップスクリプトから始めて、基本的な進捗に必要なものをインストールするだけです。私たちはまだ多くの依存関係やpostgresqlを使用しません、私たちはただ基本的なHTTPサーバーを上げて、それが完了したときにそれを認証することを心配します。 HTTPS証明書を取得し、サーバーを安全に実行するには、サーバーをレンタルすることとともにドメインを購入する必要があります。今のところ、このファイルの「チーム」をユーザーの名前に置き換え、プロジェクトのディレクトリに「dir」を置き、<>タグにメールとドメインを提供します。 さらに、このコードを実行する前に、ホスティングプロバイダーがサポートしている場合、設定をファイアウォールに変更する必要があります。通常、これはホスティングプロバイダーの「ネットワーク」タブにあります。また、セルフホスティングの場合は、ルーターの「ポート転送」セクションにあります。また、セルフホスティングを使用している場合は、サーバーマシンのアドレスを使用してルーターを介して静的IPをセットアップする必要があります。読み取り/書き込みアクセスのために、次のポートを開く必要があります。 22(SSH) 25(メール) 587(メール) 110(メールクライアント) 80(http) 443

# ! / bin / bash
SECONDS=0
PYTHON_VERSION=3.12
echo "femmebabe installer initialized."
DIR="/home/team/<yourproject>"
USER="team"
# ログコマンド
echo "Logging commands"
sudo cp log/commands.log /var/log/commands.log
sudo chmod -R a+w /var/log
sudo chown -R :syslog /var/log
echo $'alias venv="source /home/team/femmebabe/venv/bin/activate"' | sudo tee -a /home/team/.profile
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a /etc/bashrc
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a "/home/team/.bashrc"
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a /root/.bashrc
echo "source /etc/bashrc" | sudo tee -a /home/team/.profile
echo "/var/log/commands.log" | sudo tee -a /etc/logrotate.d/syslog
echo "local6.*    /var/log/commands.log" | sudo tee -a "/etc/rsyslog.d/bash.conf"
sudo service rsyslog restart
# nano config
echo "set tabsize 4" >> .nanorc
echo "set tabstospaces" >> .nanorc
# git config
echo "Git configuration"
sudo git config --global user.email "<youremail>@gmail.com" && sudo git config --global user.name "<yourname>"
git config --global --add safe.directory $"$DIR"
sudo ssh-keyscan -t rsa gitlab.com | sudo tee -a /root/.ssh/known_hosts
sudo ssh-keyscan -t rsa github.com | sudo tee -a /root/.ssh/known_hosts
# 更新してインストールします
echo "Update and install packages"
sudo apt update && sudo NEEDRESTART_MODE=a apt upgrade -y
sudo apt purge postgresql-client-14 postgresql-client-common postgresql-common postgresql-contrib postgresql -y
echo "postfix postfix/mailname string femmebabe.com" | sudo debconf-set-selections
echo "postfix postfix/main_mailer_type string 'Internet Site'" | sudo debconf-set-selections
sudo NEEDRESTART_MODE=a DEBIAN_FRONTEND=noninteractive apt install -y postfix
sudo NEEDRESTART_MODE=a apt install -y rkhunter clamav-daemon libx264-dev ffmpeg libapache2-mod-wsgi-py3 apache2 cmake python-is-python3 python3-venv python3-pip python3-django expect tesseract-ocr openjdk-8-jdk redis-server libopencv-dev python3-opencv python3-dev libsasl2-dev opendkim opendkim-tools dovecot-core dovecot-pop3d dovecot-imapd auditd procmail libpq-dev postgresql postgresql-contrib libheif-dev snapd git software-properties-common certbot python3-certbot-apache
# クラマブアンチウイルスを有効にします
echo "Starting antivirus"
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# ホスト名を設定します
echo "127.0.0.1 femmebabe" | sudo tee -a /etc/hosts
sudo hostnamectl set-hostname femmebabe
# バックアップデータベースのセットアップ
echo "Building database from backup, this may take a while."
cat db.json.?? > db.json
echo "Configuring firewall"
sudo ufw default allow outgoing
sudo ufw default deny incoming
sudo ufw allow 22
sudo ufw allow http
sudo ufw allow https
sudo ufw allow 'Postfix'
sudo ufw allow 'Postfix SMTPS'
sudo ufw allow 'Postfix Submission'
sudo ufw allow 'Dovecot POP3'
sudo ufw allow 'Dovecot Secure POP3'
sudo ufw allow 110/tcp
sudo ufw allow 25/tcp
echo "y" | sudo ufw enable
# 無効化されたiPatables
echo "Configuring firewall"
sudo iptables -P INPUT ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -F
sudo iptables-save
# Setup Virtualenv
cd $DIR
echo "Creating virtual environment"
python -m venv venv
source venv/bin/activate
pip3 install -r requirements.txt
# certbotをインストールします
echo "Installing certificates"
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo snap install redis
sudo systemctl enable apache2
sudo systemctl start apache2
# certbotを実行します
sudo certbot --apache --non-interactive --agree-tos --domains femmebabe.com --email <youremail>@gmail.com
# ユーザー設定を設定します
sudo gpasswd -a www-data users
# 設定権限
echo "Setting permissions"
sudo chown -R team:users cache/
sudo chmod a+rwx -R cache/
# sudo chown -rチーム:ユーザー/var/run/
# sudo chownルート:root/run/sudo/ts -r
sudo chown -R redis:redis /var/lib/redis
sudo chown -R redis:redis /var/log/redis
sudo chmod -R u+rwX,g+rwX,u+rx /var/log/redis
sudo chmod +r /etc/redis/redis.conf
sudo chown -R team:users /var/log/
sudo chown -R :users .././
sudo chmod -R g+rwX ./
sudo chmod -R g+rX .././
sudo chmod -R g-rwX ../.ssh
sudo chmod 774 ./
sudo chown -R www-data:www-data media/
sudo chown www-data:users ./
sudo chown -R team:users media/
sudo chown -R team:users ./
# サービスをリロードおよび有効にします
echo "Enabling services"
sudo systemctl daemon-reload
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Apacheモジュールを有効にします
echo "Enabling apache2"
sudo a2enmod rewrite
sudo a2enmod wsgi
sudo a2enmod headers
sudo a2enmod ssl
sudo a2enmod proxy
sudo a2enmod proxy_balancer
sudo a2enmod proxy_http
sudo a2enmod proxy_wstunnel
# デーモンをリロードし、アパッチ、ポストフィックス、opendkimを再起動します
sudo systemctl daemon-reload
sudo systemctl restart apache2
sudo systemctl restart opendkim postfix
# ドメイン構成のIPv6とOpendKimを表示します
echo "COPY the below information to domain configuration."
hostname -I
ip a | grep inet
ip -6 addr | grep "scope link"
このコードを実行する前に、購入したドメインがサーバーに接続されていることを確認してください。これを行うには、ローカルマシンで端末を開き、ドメインでこのコマンドを実行します。

ping femmebabe.com # pingの後、ここにドメインを挿入します
すべてがうまく見える場合、サーバーが応答を送信している場合、スクリプトを実行してパッケージをインストールし、Apacheサーバーを開始、有効化、証明する準備ができています。 これは、Postfixの構成に必要なすべてのセットアップではありません。後でそのセットアップを詳しく調べます。とりあえず、このセットアップコードを実行すると、サーバーのインストールと証明に数分かかるはずです。もう一度、購入した名前に従ってスクリプト内の名前、電子メール、ドメイン名を必ず置き換えてください。 サーバーがプロビジョニングされたので、任意のWebブラウザのURLに移動し、サーバーがHTTPSを実行していることを確認することができます。そうでない場合は、DNSレコードが追いつくのを少し待ってから、次のコマンドを実行してCertBot認定を再試行してください。

sudo certbot --apache --non-interactive --agree-tos --domains <domain>.com --email <youremail>@gmail.com
すべてを正しく構成している限り、コードが機能していることを知るために、Apacheのデフォルトページにアクセスできるはずです。次に、settings.pyを編集して、デフォルトのデバッグモードを生産に変更しましょう。また、内部IPSだけでなく、設定のドメインも構成します。

nano yourproject/settings.py
設定で、これらの行を変更/追加します。

DEBUG = False

# サイト構成
SITE_NAME = 'Femme Babe'
PROTOCOL = 'https'
DOMAIN = 'femmebabe.com'
SITE_ID = 1
BASE_URL = PROTOCOL + '://' + DOMAIN
ALLOWED_HOSTS = [DOMAIN]

INTERNAL_IPS = [
    'XX.XX.XX.XX',
]
これで、apache2を構成する必要があります。この行で展開する構成ファイルを編集しましょう。

sudo nano /etc/apache2/sites-available/femmebabe-le-ssl.conf
この構成ファイルには、ドメイン名とユーザーとプロジェクトの名前があります。ドメイン名Femmebabe.com、ユーザー名チーム、およびプロジェクト名Femmebabeを使用しています。

ServerSignature Off
ServerTokens Prod
<IfModule mod_ssl.c>
<VirtualHost *:80> 
	Redirect permanent / https://femmebabe.com/
</VirtualHost>
<VirtualHost *:443>
	ServerName femmebabe.com
	ServerAdmin team@femmebabe.com
	DocumentRoot /var/www/html

	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined
	
	Alias /static /home/team/femmebabe/static
	<Directory /home/team/femmebabe/static>
		Require all granted
	</Directory>

Alias /media/icons /home/team/femmebabe/media/
<Directory /home/team/femmebabe/media>
Require all granted
</Directory>

	<Directory /home/team/femmebabe/femmebabe>
		<Files wsgi.py>
			Require all granted
		</Files>
	</Directory>

	WSGIScriptAlias / /home/team/femmebabe/femmebabe/wsgi.py
	WSGIDaemonProcess femmebabe python-path=/home/team/femmebabe/ python-home=/home/team/femmebabe/venv header-buffer-size=100000000000 user=team
	WSGIProcessGroup femmebabe
	WSGIApplicationGroup %{GLOBAL}
	
	<Directory /home/team/femmebabe/static>
                Options Indexes FollowSymLinks
                AllowOverride All
	</Directory>

	<IfModule mod_rewrite.c>
		RewriteEngine on
		RewriteCond %{REQUEST_URI} \.(css|webp|webm|gif|png|mp3|wav|jpeg|jpg|svg|webp)$ [NC]
		RewriteCond %{HTTP_REFERER} !^https://femmebabe.com/media/.*$ [NC]
		RewriteRule ^(.+?)/$ /media/$1 [F,L]
	</IfModule>

	Include /etc/letsencrypt/options-ssl-apache.conf
	SSLCertificateFile /etc/letsencrypt/live/femmebabe.com/fullchain.pem
	SSLCertificateKeyFile /etc/letsencrypt/live/femmebabe.com/privkey.pem

	Header set X-Frame-Options: "SAMEORIGIN"
	Header set Access-Control-Allow-Origin "https://femmebabe.com"

	TimeOut 60000
	LimitRequestBody 0

	<FilesMatch ".(ico|pdf|flv|jpg|jpeg|png|gif|webp|JPG|JPEG|wav|mp3|mp4|public|js|css|swf|webp|svg)$">
		Header set Cache-Control "max-age=30, public"
	</FilesMatch>
</VirtualHost>
</IfModule>
<IfModule mod_ssl.c>
<VirtualHost *:80>
	ServerName femmebabe.com
	ServerAdmin team@femmebabe.com
	DocumentRoot /var/www/html

	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined

	RewriteEngine on
	RewriteCond %{SERVER_NAME} =femmebabe.com
	RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
</IfModule>
サーバーを構成するときは、この例コードのプロジェクト、ディレクトリ、およびドメインの名前を必ず置き換えてください。これで、デフォルトのサイトを無効にする必要があります。これは、bashを使用して実行できます。

sudo a2dissite 000-default-le-ssl
sudo a2dissite 000-default
sudo a2dissite default-ssl
次に、bashを使用して、デフォルトのサイトを有効にし、apache2をリロードできます。 femmebabeを、/etc/apache2/sites-abaible/で編集するときに宣言したファイルの名前に置き換えることを忘れないでください。

sudo a2ensite femmebabe-le-ssl
sudo systemctl reload apache2
Navbarのドメインに戻ります。 Webブラウザで構成したサイトが表示されます。おめでとう!表示されない場合は、いくつかの変更を加える必要がある場合があります。プロジェクトの設定、Apache Configurationを慎重に確認し、エラーがないことを確認し、次のコマンドを実行してプロジェクトにエラーを確認します。

cd projectname
source venv/bin/activate
python manage.py check
Pythonプロジェクトにエラーがある場合は、それらをどこにいるかまでトレースして修正します。エラーがどこにあるかに応じてすべてのエラーを表示できない場合があるため、単に「copulateがリエントラントではない」というエラーがある場合は、仮想環境で次のファイルを編集して、registry.pyで編集して、エラー。

nano venv/lib/python3.12/site-packages/django/apps/registry.py
このランタイムエラーが発生する83行目にスクロールし(RuntimeError(“ Populate()resentrant "ではない」)、この行の前にコメントを追加してから、同じインデントでself.app_configs = {}を追加します。これは次のようになります:

            if self.loading:
                # appconfig.ready()の実行を避けるためにリエントラントコールを防ぐ
                # 方法は2回。
# RuntimeErrorをRaise( "Populate()は再入力していません")
                self.app_configs = {}
            self.loading = True
その後、プロジェクトをもう一度確認して、エラーを公開できます。

python manage.py check
次に、エラーを確認して修正できます。修正して、コードがエラーなしでコンパイルされたら、ファイルを必ず変更して、次のようになります。

            if self.loading:
                # appconfig.ready()の実行を避けるためにリエントラントコールを防ぐ
                # 方法は2回。
                raise RuntimeError("populate() isn't reentrant")
# self.app_configs = {}
            self.loading = True
サーバーがオンラインである場合、さらに変更を加えると、次のコマンドを使用してサーバーをリロードする必要があります。

sudo systemctl reload apache2
素晴らしい!しかし、メールを送信するのはどうですか?メールの送信を開始するには、最初にドメイン構成を更新する必要があります。これは、SquarespaceのDNSパネル、または選択したドメイン名レジストラにある必要があります。また、設定をインストールして追加し、いくつかのコマンドを実行する必要があります。 まず、サーバーのIPv6アドレスを取得しましょう。その後、DNSを開き、レコードを追加します。 サーバーのIPv6アドレスを取得するには、このコマンドを使用します。

ip -6 addr
これで、次のレコードをDNS設定に追加できます。私のレコードはこのように見えます。ただし、レコードの場合、IPアドレスをIPに置き換える必要があります(75.147.182.214ではなく、それが私のものです)。また、Femmebabe.comの代わりにドメインを追加し、前のコマンドで見つかったIPv6アドレスを追加します(Mine、FE80 :: 725A:FFF:FE49:3E02を使用できません)。今のところDomainKeyについて心配しないでください。これは、Postfix、Mail Server、OpendKimを使用してキーを印刷するときに作成されます。最後に構成します。 @ a n/a 75.147.182.214 @ MX 10 femmebabe.com @ Ptr n/a femmebabe.com @ TXT n/a Txt @ V = SPF1 MX IP75.147.182.214IP6:FE80 :: 725A:FFF:FE49:3E02〜ALL default._bimi TXT n/a v = bimi1; l = https://femmebabe.com/media/static/femmebabe.svg _dmarc TXT n/a V = DMARC1; p =なし sendonly._domainkey TXT n/a次に、Postfixに持続的な構成を追加する必要があります。必要なのは、ドメイン名、Femmebabe.comを使用しているドメイン名に置き換えることです。すべての構成ファイルを1つずつ見て、OSにインストールするために、プロジェクトのConfig Configというディレクトリにインストールします。

nano config/etc_postfix_main.cf
このテキストをファイルに追加します

# /usr/share/postfix/main.cf.distを参照してください


# Debian固有:ファイル名を指定すると、最初のものが発生します
# そのファイルの行は、名前として使用されます。  Debianデフォルト
# /etc /mailNameです。
# myorigin = /etc /mailName

smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no

# Appling .DomainはMUAの仕事です。
append_dot_mydomain = no

# 次の行を解除して、「遅延メール」警告を生成します
# delay_warning_time = 4h

readme_directory = no

# http://www.postfix.org/compatibility_readme.htmlを参照してください - デフォルトは3.6オンです
# 新鮮なインストール。
compatibility_level = 3.6



# TLSパラメーター
smtpd_tls_cert_file=/etc/letsencrypt/live/femmebabe.com/fullchain.pem
smtpd_tls_key_file=/etc/letsencrypt/live/femmebabe.com/privkey.pem
smtpd_tls_security_level=may

smtp_tls_CApath=/etc/ssl/certs
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

smtpd_relay_restrictions = permit_sasl_authenticated, defer_unauth_destination
myhostname = femmebabe.com
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = femmebabe.com, localhost, $myhostname
smtp_helo_name = femmebabe.com
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all

# Milter構成
milter_default_action = accept
milter_protocol = 6
smtpd_milters = local:/opendkim/opendkim.sock
non_smtpd_milters = $smtpd_milters

smtp_tls_security_level = encrypt
smtp_tls_loglevel = 1

virtual_transport=lmtp:unix:private/dovecot-lmtp

smtpd_sasl_path = private/auth
次の構成!

nano config/etc_postfix_master.cf
これらの行を追加します:

# 
# Postfixマスタープロセス構成ファイル。  フォーマットの詳細については
# ファイルについては、マスター(5)マニュアルページ(コマンド: "Man 5 Master"または
# オンライン:http://www.postfix.org/master.5.html)。
# 
# このファイルを編集した後、「ポストフィックスリロード」を実行することを忘れないでください。
# 
# =========================================================== ======================
# サービスタイププライベートUNPRIV Chroot WakeUp MaxProc Command + Args
# (はい)(はい)(いいえ)(決して)(100)
# =========================================================== ======================
smtp      inet  n       -       y       -       -       smtpd
# smtp inet n -y -1ポストスクリーン
# SMTPDパス -  Y-SMTPD
# dnsblog unix-- y -0 dnsblog
# tlsproxy unix -y -0 tlsproxy
# 1つを選択します。Loopbackクライアントのみ、またはクライアントに送信を有効にします。
# 127.0.0.1:submission inet n -y- smtpd
submission inet n       -       y       -       -       smtpd
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_tls_wrappermode=no
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
# -o syslog_name = postfix/submission
# -o smtpd_tls_security_level = encrypt
# -o smtpd_sasl_auth_enable = yes
# -o smtpd_tls_auth_only = yes
# -o smtpd_reject_unlisted_recipient = no
# -o smtpd_client_restrictions = $ mua_client_restrictions
# -o SMTPD_HELO_RESTRICTIONS = $ MUA_HELO_RESTRICTIONS
# -o smtpd_sender_restrictions = $ mua_sender_restrictions
# -o SMTPD_RECIPIENT_TRASTRICTIONS =
# -o SMTPD_RELAY_RESTRICTIONS = permit_sasl_authenticated、拒否
# -o milter_macro_daemon_name = originating
# 1つを選択します。Loopbackクライアントのみ、またはクライアントのSMTPSを有効にします。
# 127.0.0.1:SMTPS INET N -Y- SMTPD
# smtps inet n -y- smtpd
# -o syslog_name = postfix/smtps
# -o smtpd_tls_wrappermode = yes
# -o smtpd_sasl_auth_enable = yes
# -o smtpd_reject_unlisted_recipient = no
# -o smtpd_client_restrictions = $ mua_client_restrictions
# -o SMTPD_HELO_RESTRICTIONS = $ MUA_HELO_RESTRICTIONS
# -o smtpd_sender_restrictions = $ mua_sender_restrictions
# -o smtpd_recipient_restrictions =
# -o SMTPD_RELAY_RESTRICTIONS = permit_sasl_authenticated、拒否
# -o milter_macro_daemon_name = originating
# 628 inet n -y- qmqpd
pickup    unix  n       -       y       60      1       pickup
cleanup   unix  n       -       y       -       0       cleanup
qmgr      unix  n       -       n       300     1       qmgr
# Qmgr unix n -n 300 1 oqmg
tlsmgr    unix  -       -       y       1000?   1       tlsmgr
rewrite   unix  -       -       y       -       -       trivial-rewrite
bounce    unix  -       -       y       -       0       bounce
defer     unix  -       -       y       -       0       bounce
trace     unix  -       -       y       -       0       bounce
verify    unix  -       -       y       -       1       verify
flush     unix  n       -       y       1000?   0       flush
proxymap  unix  -       -       n       -       -       proxymap
proxywrite unix -       -       n       -       1       proxymap
smtp      unix  -       -       y       -       -       smtp
relay     unix  -       -       y       -       -       smtp
        -o syslog_name=postfix/$service_name
# -o smtp_helo_timeout = 5 -o smtp_connect_timeout = 5
showq     unix  n       -       y       -       -       showq
error     unix  -       -       y       -       -       error
retry     unix  -       -       y       -       -       error
discard   unix  -       -       y       -       -       discard
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       y       -       -       lmtp
anvil     unix  -       -       y       -       1       anvil
scache    unix  -       -       y       -       1       scache
postlog   unix-dgram n  -       n       -       1       postlogd
# 
# =========================================================== =================
# 非ポストフィックスソフトウェアへのインターフェイス。必ずマニュアルを調べてください
# 非Postfixソフトウェアのページでは、必要なオプションを確認します。
# 
# 次のサービスの多くは、ポストフィックスパイプ(8)配達を使用しています
# エージェント。  $ {受信者}についての情報については、パイプ(8)女性ページを参照してください
# その他のメッセージエンベロープオプション。
# =========================================================== =================
# 
# メールドロップ。詳細については、postfix maildrop_readmeファイルを参照してください。
# また、main.cf:maildrop_destination_recipient_limit = 1で指定します
# 
maildrop  unix  -       n       n       -       -       pipe
  flags=DRXhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
# 
# =========================================================== =================
# 
# 最近のCyrusバージョンは、既存の「LMTP」Master.CFエントリを使用できます。
# 
# Cyrus.confで指定します:
# lmtp cmd = "lmtpd -a" listen = "localhost:lmtp" proto = tcp4
# 
# main.cfで指定します。
# Mailbox_transport = lmtp:inet:localhost
# virtual_transport = lmtp:inet:localhost
# 
# =========================================================== =================
# 
# サイラス2.1.5(Amos Gouaux)
# また、main.cf:cyrus_destination_recipient_limit = 1で指定します
# 
# Cyrus Unix -N N-パイプ
# flags = drx user = cyrus arg =/cyrus/bin/derivial -e -r $ {sender} -m $ {extension} $ {user}
# 
# =========================================================== =================
# サイラスを介した配達の古い例。
# 
# old -cyrus unix -n n  - パイプ
# flags = r user = cyrus argv =/cyrus/bin/derivie -e -m $ {endoxt} $ {user}
# 
# =========================================================== =================
# 
# 構成の詳細については、Postfix uucp_readmeファイルを参照してください。
# 
uucp      unix  -       n       n       -       -       pipe
  flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
# 
# その他の外部配信方法。
# 
ifmail    unix  -       n       n       -       -       pipe
  flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
bsmtp     unix  -       n       n       -       -       pipe
  flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
scalemail-backend unix -       n       n       -       2       pipe
  flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
mailman   unix  -       n       n       -       -       pipe
  flags=FRX user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py ${nexthop} ${user}
およびOpendKim構成。 OpendKimは、ドメインキーを備えた電子メールサーバーを識別して、より安全にします。それがなければ、メールは署名されておらず、受信トレイに登場しない可能性があります。

nano config/etc_default_opendkim
これらの行を追加します:

# 注:これはレガシー構成ファイルです。 OpendKimで使用されていません
# SystemDサービス。対応する構成パラメーターを使用してください
# /etc/opendkim.conf代わりに。
# 
# 以前は、ここでデフォルト設定を編集してから実行します
# /lib/opendkim/opendkim.service.generate systemd overrideファイルを生成します
# /etc/systemd/system/opendkim.service.d/override.conf and
# /etc/tmpfiles.d/opendkim.conf。これはまだ可能ですが、今です
# /etc/opendkim.confで設定を直接調整することをお勧めします。
# 
# daemon_opts = ""
# /var/spool/postfix/run/opendkimに変更して、unixソケットを使用します
# chrootのポストフィックス:
# rundir =/var/spool/postfix/run/opendkim
RUNDIR=/run/opendkim
# 
# 代替ソケットを指定するための障害
# これを設定すると、opendkim.confのソケット値がオーバーライドされることに注意してください
# デフォルト:
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
# ポート54321のすべてのインターフェイスで聞く:
# Socket = INET:54321
# ポート12345のループバックで聞く:
# socket = inet:12345@localhost
# 聞くことは192.0.2.1ポート12345です。
# socket = inet:12345@192.0.2.1
USER=opendkim
GROUP=opendkim
PIDFILE=$RUNDIR/$NAME.pid
EXTRAAFTER=

nano config/etc_dovecot_conf.d_10-master.conf
これらの行を追加します:

0-master.conf 
# default_process_limit = 100
# default_client_limit = 1000

# サービスプロセスのデフォルトVSZ(仮想メモリサイズ)制限。これは主にです
# 彼らが食事をする前にメモリを漏らすプロセスをキャッチして殺すことを意図した
# すべて。
# default_vsz_limit = 256m

# ログインユーザーは、ログインプロセスで内部的に使用されます。これは最も信頼されていないものです
# dovecotシステムのユーザー。何にもアクセスできないはずです。
# default_login_user = dovenull

# 内部ユーザーは、特権のないプロセスで使用されます。それは別にする必要があります
# ログインユーザー、ログインプロセスが他のプロセスを妨害できないようにします。
# default_internal_user = dovecot

service imap-login {
  inet_listener imap {
    # ポート= 143
  }
  inet_listener imaps {
    # ポート= 993
    # SSL =はい
  }

  # 新しいプロセスを開始する前に処理する接続の数。通常
  # 唯一の有用な値は0(無制限)または1。1の方が安全ですが、0
  # より速いです。 <doc/wiki/loginprocess.txt>
  # service_count = 1

  # 常により多くの接続を待ち続けるプロセスの数。
  # process_min_avail = 0

  # service_count = 0を設定した場合、おそらくこれを成長させる必要があります。
  # vsz_limit = $ default_vsz_limit
}

service pop3-login {
  inet_listener pop3 {
    # ポート= 110
  }
  inet_listener pop3s {
    # ポート= 995
    # SSL =はい
  }
}

service submission-login {
  inet_listener submission {
    # ポート= 587
  }
}

service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    group = postfix
    mode = 0666
    user = postfix
  }

  # 上記のUNIXソケットを使用できない場合にのみINETリスナーを作成します
  # inet_lister lmtp {
    # インターネット全体にLMTPを表示しないでください
    # アドレス=
    # port =
  # }
}

service imap {
  # ほとんどのメモリは、MMAP()ingファイルに移動します。これを増やす必要があるかもしれません
  # 巨大なメールボックスがある場合は制限します。
  # vsz_limi = $ default_vsz_limit

  # マックス。 IMAPプロセスの数(接続)
  # process_limit = 1024
}

service pop3 {
  # マックス。 POP3プロセスの数(接続)
  # process_limit = 1024
}

service submission {
  # マックス。 SMTP提出プロセスの数(接続)
  # process_limit = 1024
}

service auth {
  # auth_socket_pathは、デフォルトでこのuserdbソケットを指しています。通常です
  # dovecot-lda、doveadm、おそらくimapプロセスなどが使用しているユーザー
  # このソケットへの完全な権限は、すべてのユーザー名のリストを取得できます。
  # 全員のuserDBルックアップの結果を取得します。
  # 
  # デフォルトの0666モードを使用すると、誰でもソケットに接続できますが、
  # userdbルックアップは、userdbが「uid」フィールドを返す場合にのみ成功します。
  # 発信者プロセスのUIDに一致します。また、発信者のUIDまたはGIDが一致する場合
  # ソケットのuidまたはgid lookupが成功します。他のものは失敗を引き起こします。
  # 
  # すべてのユーザーを検索するために発信者に完全な権限を与えるには、モードをに設定します
  # 0666以外の何かとdovecotを使用すると、カーネルが強制されます
  # 権限(たとえば、0777を使用すると、全員が完全な権限を許可します)。
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }
}

service auth-worker {
  # Auth Workerプロセスはデフォルトでルートとして実行されるため、アクセスできるように
  # /など/影。これが必要ない場合、ユーザーはに変更する必要があります
  # $ default_interal_user。
  # user = root
}

service dict {
  # DICTプロキシを使用する場合、メールプロセスはソケットにアクセスできるはずです。
  # 例:mode = 0660、group = vmail、およびglobal mail_access_groups = vmail
  unix_listener dict {
    # モード= 0600
    # ユーザー=
    # グループ=
  }
}
もう一度、これらのすべてのファイルのドメイン、Femmebabe.comを選択したドメインに置き換えるようにしてください。次のファイル、dovecotの構成を編集します。

nano config/etc_dovecot_dovecot
これらの行を追加します

## ovecot構成ファイル

# 急いでいる場合は、http://wiki2.dovecot.org/quickconfigurationを参照してください

# 「doveconf -n」コマンドは、変更された設定のクリーンな出力を提供します。使用してください
# dovecotメーリングリストに投稿するときにファイルをコピーして貼り付ける代わりに。

# '# 'キャラクターとそれがコメントとして扱われた後のすべて。余分なスペース
# タブは無視されます。これらのいずれかを明示的に使用したい場合は、
# value inside quotes, eg.: key = "# チャーとトレーリングホワイトスペース」

# ほとんどの(すべてではありませんが)設定は、異なるプロトコルおよび/または
# セクション内に設定を配置して、ソース/宛先IPSなど:
# プロトコルIMAP {}、ローカル127.0.0.1 {}、リモート10.0.0.0/8 {}

# 各設定のデフォルト値が表示され、除外する必要はありません
# それらの。ただし、これらの例外です:セクションなし(例:名前空間{})
# または、プラグインの設定がデフォルトで追加され、それらは例としてのみリストされています。
# パスは単なる例であり、実際のデフォルトは構成に基づいています
# オプション。ここにリストされているパスは、configure  -  -prefix =/usrです
# -sysconfdir =/etc -localStatedir =/var

# インストールされたプロトコルを有効にします
!include_try /usr/share/dovecot/protocols.d/*.protocol

# 接続のために耳を傾ける場所またはホストのコンマ分離されたリスト。
# "*"すべてのIPv4インターフェイスで聴きます "::"すべてのIPv6インターフェイスで聴きます。
# 非デフォルトポートなどを指定する場合は、より複雑なものを指定したい場合は、
# conf.d/master.confを編集します。
# 聞く= *、::

# ランタイムデータを保存するベースディレクトリ。
# base_dir =/var/run/dovecot/

# このインスタンスの名前。 Multi-InstanceのセットアップDoveadmおよびその他のコマンド
# -i <intance_name>を使用して使用するインスタンスを選択できます(代替案
# -c <config_path>へ)。インスタンス名もdovecotプロセスに追加されます
# PS出力で。
# instance_name = dovecot

# クライアントへの挨拶メッセージ。
# login_greeting = dovecot ready。

# 信頼できるネットワーク範囲のスペース分離リスト。これらからの接続
# IPはIPアドレスとポートをオーバーライドすることができます(ロギング用と
# 認証チェック用)。 disable_plaintext_authも無視されます
# これらのネットワーク。通常、ここでIMAPプロキシサーバーを指定します。
# login_trusted_networks =

# ログインアクセスチェックソケットのスペース分離リスト(TCPWRAPなど)
# login_access_sockets =

# proxy_maybe =はい、プロキシ宛先がこれらのipsのいずれかに一致する場合、しないでください
# プロキシ。これは正常に必要ではありませんが、目的地の場合は便利かもしれません
# IPは例えばロードバランサーのIP。
# auth_proxy_self =

# より多くの冗長プロセスタイトル(PS)を表示します。現在、ユーザー名と
# IPアドレス。誰が実際にIMAPプロセスを使用しているのかを見るのに便利です
# (たとえば、共有メールボックスまたは複数のアカウントに同じUIDが使用されている場合)。
# verbose_procitle = no

# DoveCotマスタープロセスがシャットダウンすると、すべてのプロセスが殺される場合。
# これを「いいえ」に設定することは、DoveCotをなしでアップグレードできることを意味します
# 既存のクライアント接続を強制することを強制します(ただし、
# アップグレードがたとえばの場合の問題セキュリティ修正のため)。
# shutdown_clients =はい

# ゼロ以外の場合は、DoveAdMサーバーへのこの多くの接続を介してメールコマンドを実行します。
# 同じプロセスで直接実行する代わりに。
# doveadm_worker_count = 0
# UNIXソケットまたはホスト:DOVEADMサーバーへの接続に使用されるポート
# doveadm_socket_path = doveadm-server

# dovecotに保存されている環境変数のスペース分離リスト
# スタートアップとそのすべての子プロセスに渡されました。あなたも与えることができます
# key = valueペア常に特定の設定を設定します。
# import_environment = tz

## 
## 辞書サーバー設定
## 

# 辞書は、key = valueリストを保存するために使用できます。これはいくつかで使用されます
# プラグイン。辞書には直接または
# 辞書サーバー。次のDICTブロックマップ辞書名はURISに
# サーバーが使用されるとき。これらは、urisを使用して形式で参照できます
# 「プロキシ:: <Name>」。

dict {
  # quota = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext
}

# 実際の構成のほとんどは以下に含まれます。ファイル名はそうです
# 最初にASCII値でソートされ、その順序で解析されます。 00-prefixes
# ファイル名では、注文を理解しやすくすることを目的としています。
!include conf.d/*.conf

# 設定ファイルは、エラーを与えずに含めることもできました
# 見つかりません:
!include_try local.conf

passdb {
  driver = passwd-file
  args = /etc/dovecot/passwd
}
userdb {
  driver = passwd
}

protocols = imap pop3

# dovecotがすべての入力接続を聴くことができます(IPv4 / IPv6)

listen = *, ::
dovecotユーザーのパスワードを追加します。

nano config/etc_dovecot_passwd
コロンの前のファイルの最初の部分はユーザー名です。最後の部分「YourPassWord」は、メールサーバーを提供するパスワードを示します。

team:{plain}yourpassword
次に、opendkim config

nano config/etc_opendkim.conf
これらの行を追加します:

# これは、署名と検証のための基本的な構成です。簡単にすることができます
# 基本的なインストールに合わせて適応します。 opendkim.conf(5)および
# /usr/share/doc/opendkim/examples/opendkim.conf.sampleを完全に
# 使用可能な構成パラメーターのドキュメント。

Syslog			yes
SyslogSuccess		yes
# logwhy no

# 一般的な署名と検証パラメーター。 Debianでは、「From」ヘッダーです
# それは多くの場合、評判システムが使用するアイデンティティキーであるため、オーバー署名しました
# したがって、ややセキュリティに敏感です。
Canonicalization	relaxed/simple
Mode			s
SubDomains		no
OversignHeaders		From

# 署名ドメイン、セレクター、およびキー(必須)。たとえば、署名を実行します
# セレクター「2020」(2020.domainkey.example.com)を備えたドメイン「embler.com」
# /etc/dkimkeys/example.privateに保存されている秘密鍵を使用します。もっと粒状
# セットアップオプションは/usr/share/doc/opendkim/readme.opendkimにあります。
# domain emple.com
# セレクター2020
# keyfile /etc/dkimkeys/example.private

# Debianでは、OpendKimはユーザー「OpendKim」として実行されます。 007のumaskが必要です
# SocketにアクセスしていないMTAを備えたローカルソケットを使用していない
# ユーザー(たとえば、postfix)。ユーザー「Postfix」をグループに追加する必要がある場合があります
# その場合の「Opendkim」。
UserID			opendkim
UMask			007

# MTA接続用ソケット(必須)。 MTAがChroot刑務所の中にある場合、
# ソケットにアクセスできるようにする必要があります。 Debianでは、Postfixが実行されます
# /var/spool/postfixのchroot、したがって、unixソケットは
# 以下の最後の行に示されているように構成されています。
# ソケットローカル:/run/opendkim/opendkim.sock
# Socket Inet:8891@localhost
# ソケットINET:8891
Socket			local:/var/spool/postfix/opendkim/opendkim.sock

PidFile			/run/opendkim/opendkim.pid

# 検証するのではなく署名するホスト、デフォルトは127.0.0.1です。を参照してください
# 詳細については、OpendKim(8)の操作セクション。
# 内部ホスト192.168.0.0/16、10.0.0.0/8、172.16.0.0/12

# トラストアンカーはDNSSECを有効にします。 Debianでは、Trust Anchorファイルが提供されます
# パッケージDNS-ROOT-DATAによって。
TrustAnchorFile		/usr/share/dns/root.key
# 名前サーバー127.0.0.1

# アドレスからメッセージに署名するために使用されるキーまでのドメインをマップする
KeyTable           refile:/etc/opendkim/key.table
SigningTable       refile:/etc/opendkim/signing.table

# メールに署名すべき内部ホストのセット
InternalHosts       /etc/opendkim/trusted.hosts

nano config/etc_default_opendkim
これらの行を追加します

# 注:これはレガシー構成ファイルです。 OpendKimで使用されていません
# SystemDサービス。対応する構成パラメーターを使用してください
# /etc/opendkim.conf代わりに。
# 
# 以前は、ここでデフォルト設定を編集してから実行します
# /lib/opendkim/opendkim.service.generate systemd overrideファイルを生成します
# /etc/systemd/system/opendkim.service.d/override.conf and
# /etc/tmpfiles.d/opendkim.conf。これはまだ可能ですが、今です
# /etc/opendkim.confで設定を直接調整することをお勧めします。
# 
# daemon_opts = ""
# /var/spool/postfix/run/opendkimに変更して、unixソケットを使用します
# chrootのポストフィックス:
# rundir =/var/spool/postfix/run/opendkim
RUNDIR=/run/opendkim
# 
# 代替ソケットを指定するための障害
# これを設定すると、opendkim.confのソケット値がオーバーライドされることに注意してください
# デフォルト:
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
# ポート54321のすべてのインターフェイスで聞く:
# Socket = INET:54321
# ポート12345のループバックで聞く:
# socket = inet:12345@localhost
# 聞くことは192.0.2.1ポート12345です。
# socket = inet:12345@192.0.2.1
USER=opendkim
GROUP=opendkim
PIDFILE=$RUNDIR/$NAME.pid
EXTRAAFTER=
Postfixサーバーを設定する準備ができたら、適切なドメイン名が組み込まれて、以下のコードを実行します。スクリプトを作成することから始めます

touch scripts/postfixsetup
sudo chmod a+x scripts/postfixsetup
nano scripts/postfixsetup
現在、テキストエディターのNanoで、このファイルを編集して、femmebabe.comの代わりにドメイン名を含めます。

# ! / bin / bash
# ポストフィックスをセットアップします
cd $DIR
echo "Mail services configuration"
sudo cp /etc/postfix/main.cf /etc/postfix/main.cf.backup
sudo cp config/etc_postfix_main.cf /etc/postfix/main.cf
sudo cp config/etc_postfix_master.cf /etc/postfix/master.cf
sudo cp config/etc_default_opendkim /etc/default/opendkim
sudo cp config/etc_dovecot_conf.d_10-auth.conf /etc/dovecot/conf.d/10-auth.conf
sudo cp config/etc_dovecot_conf.d_10-master.conf /etc/dovecot/conf.d/10-master.conf
sudo cp config/etc_dovecot_dovecot.conf /etc/dovecot/dovecot.conf
sudo cp config/etc_dovecot_passwd /etc/dovecot/passwd
sudo cp config/etc_opendkim.conf /etc/opendkim.conf
sudo cp config/etc_default_opendkim /etc/default/opendkim
sudo adduser postfix opendkim
sudo mkdir /etc/opendkim
sudo mkdir /etc/opendkim/keys
sudo mkdir /etc/opendkim/keys/femmebabe.com
sudo mkdir /var/spool/postfix/opendkim
sudo echo "*@femmebabe.com     sendonly._domainkey.femmebabe.com" | sudo tee -a /etc/opendkim/signing.table
sudo echo "sendonly._domainkey.femmebabe.com    femmebabe.com:sendonly:/etc/opendkim/keys/femmebabe.com/sendonly.private" | sudo tee -a /etc/opendkim/key.table
sudo echo "127.0.0.1" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "localhost" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "*.femmebabe.com" | sudo tee -a /etc/opendkim/trusted.hosts
sudo chown -R opendkim:opendkim /etc/opendkim
sudo opendkim-genkey -b 2048 -d femmebabe.com -D /etc/opendkim/keys/femmebabe.com -s sendonly -v
sudo chmod go-rw /etc/opendkim/keys
sudo chown opendkim:opendkim /etc/opendkim/keys/femmebabe.com/sendonly.private
sudo chown opendkim:postfix /var/spool/postfix/opendkim
cd $DIR
sudo cp mailbox/* /var/mail/
sudo chown :users /var/mail/*
sudo chmod -R a+rwx /var/mail/*
sudo systemctl restart opendkim postfix dovecot
sudo cat /etc/opendkim/keys/femmebabe.com/sendonly.txt | tr -d '\n' | sed 's/\s//g' | sed 's/""//g' | awk -F'[)(]' '{print $2}'
次に、完了したスクリプトを実行して、Postfix、OpendKim、DoveCotを構成します。

./scripts/postfixsetup
このスクリプトが実行されたら、最後に印刷する行をコピーして、sendonly._domainkeyの値としてDNS構成に貼り付けます。これは、安全なメールを送信するときにドメインを識別するために使用されるOpendKimキーです。 素晴らしい!数日以内に、すべてが正しく構成されている場合、サーバーからメールを送信できるはずです。 メールサーバーのDNSを構成しただけで、レコードが更新されるまで72時間未満かかるはずです。通常、はるかに速いです。このコマンドを使用してサーバーが機能しているかどうかを確認でき、メールを提供しました。

echo “test” | mail -s “Test Email” youremail@gmail.com
すべてが正しく機能しているように見える場合は、サーバーで電子メールを送信できるはずです。動作していない場合は、ログを見て、エラーが何であるかを確認してください。

tail –lines 150 /var/log/mail.log
これにより、サーバーによって送信されているメールに関する冗長な情報と、適切に機能しているかどうかが提供されます。受信トレイに電子メールも表示できるはずです。そこにない場合は、スパムフォルダーを確認してください。 また、電子メールサーバーがDjangoアプリ、プロジェクトに通信できるように、設定で設定を設定する必要があります。これらの行を設定に追加または交換します

EMAIL_HOST = DOMAIN
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_ADDRESS = 'team@femmebabe.com'
EMAIL_HOST_USER = 'team' # 「love@mamasheen.com」
EMAIL_HOST_PASSWORD = config['EMAIL_HOST_PASSWORD']
DEFAULT_FROM_EMAIL = '{} <{}>'.format(SITE_NAME, EMAIL_HOST_USER)
パスワードを取得するために構成ファイルを使用していることに注意してください。ファイルの最初に、このファイルを設定にロードしましょう。

import os
import json

# 設定を開いてロードします
with open('/etc/config.json') as config_file:
    config = json.load(config_file)
このファイルを作成して、秘密の鍵とメールのパスワードを追加しましょう。秘密の鍵を生成するには、最後に好きな長さでこのコマンドを使用してください。

openssl rand -base64 64
ここで、openSSL生成されて編集されたテキストをコピーして /etc/config.json

sudo nano /etc/config.json
OpenSSLが秘密の鍵として生成されるキーを使用して、次の行をファイルに追加します。

{
	"SECRET_KEY": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX-generated-using-openssl)",
	"EMAIL_HOST_PASSWORD": "yourpassword"
}
JSON形式はシンプルで使いやすいです。このようにしてプロジェクトで使用したい他のキーを宣言し、他のユーザーがそれらに書き込むことができないようにプロジェクトディレクトリとは別に保管しておくことができます。プロジェクトディレクトリだけから。これは、APIキーに推奨される練習です。この練習では、ここではいくつか使用します。 また、プロジェクトをバックアップして、すべてが保存されていることを確認し、サーバーをレンタルしたくない場合でも、後で作業を回復できるようになります。

sudo backup
次に、コマンドラインから送信している場合は、WebサーバーからHTMLメールを送信してみてください。シェルでユーザーインスタンスをクエリし、Djangoを介してそのユーザーにHTMLメールを送信します。コードのCharlotteの名前をユーザー名に変更します。

python manage.py shell
from django.contrib.auth.models import User
u = User.objects.get(username='Charlotte')
from users.email import send_welcome_email
send_welcome_email(u)
exit()
最初のコマンドが機能しない場合は、必ず使用してください

source venv/bin/activate
すべてが正しくセットアップされている場合は、Webアプリから送信されたメールボックスに歓迎のメールを受け取るようになりました。よくやった!あなたは長い道のりを歩んできました。 このようなプロジェクトに取り組んでいる間にエラーに苦労している場合は、回答を検索して助けを求めることをheしないでください。 Googleは、他の検索エンジンの中でも、プログラミングヘルプを検索するための優れたリソースです。あなたが得ているエラーを単に検索するだけで、他の人が問題をどのように解決するかを見ることができます。また、私に連絡してください、あなたの教育者(教師、教授、家庭教師)、インターネット上のピアプログラミングヘルプに利用できるか、この本または他のリソースを再度参照して、あなたが経験している問題の解決策を見つけてください。これは簡単ではないことを理解していますが、これまで読んでいて、コードを書いていなくても、Webアプリをゼロから構築することについて多くのことを学んでいます。背中を軽くたたいてください、あなたは素晴らしいことをしています仕事。 この第3版のWeb開発ガイドをお読みいただきありがとうございます。将来のエディションでは、ドキュメントの冒頭で説明した重要な例をもっと含め、ソフトウェアとハ​​ードウェア開発の世界に深く掘り下げます。今後のことをお楽しみに、信じられないほどのソフトウェアを構築する方法を教えてくれることを楽しみにしています。次は会いましょう






近い
ページ 1
ジャンプ
完全な記事を参照してください
読み続けます

買う | 暗号で購入します



https://glamgirlx.com/ja/practical-web-based-deep -


(クリックまたはタップして画像をダウンロード)
プロのエンターテイメント、写真、ビデオ、オーディオ、ライブストリーミング、カジュアルなゲームプレイ、IDスキャン、Web開発、代理出産サービス。

このアドレスを使用して、ビットコインにヒントを残してください。 3KhDWoSve2N627RiW8grj6XrsoPT7d6qyE

© Glam Girl X 2025

利用規約