Практичне веб-поглиблене навчання та безпека на прикладі

DaisyФото профілю

за Daisy

Практичне в Інтернеті глибоке навчання та безпека на прикладі Третє видання Шарлотта Харпер 3 липня 2024 року Передмова: Міркування щодо безпеки у створенні програмного забезпечення для Інтернету є важливою частиною плану та виконання будь -якого веб -розробника, а також інженерія прототипу, який є надійним, стабільним та корисним для практичних цілей. DOM (розмітка об'єктів документа), з його реалізацією HTML, JavaScrip Творчість, забезпечуйте простоту використання та функціональності, зображуйте смирення та характер та забезпечуйте простоту використання, а також зручність та важливі послуги, які всі привабливі для середнього Джо, кінцевого користувача, який прагне вбити час або щось зробити в Інтернеті, Зазвичай на пристрої смартфона сенсорного екрану. Більшість людей навіть не знали, з чого почати, коли хочуть створити веб -сайт з нуля,Вони, як правило, починаються на веб -сайті іншої людини і створюють щось обмежене у функціональності, надійності, простоті використання та особливо творчості, коли вони могли мати у своєму розпорядженні всі останні потужні інструменти, щоб побудувати щось корисне, не витрачаючи часу на натискання кнопки та Особливо витрачаючи гроші на оплату дорогих підписки на програмне забезпечення, які мало хто хотів використовувати, враховуючи обмеження в просторі використання та гнучкості. Якщо у вас є кілька хвилин, щоб прочитати цю книгу і дізнатися, чого я хочу навчити вас, або навіть особисто поговорити зі мною про ваші цілі та отримати певні вказівки в правильному напрямку, і мотивовані навчитися кодувати та писати власне програмне забезпечення , Візьміть цю книгу додому і відкладіть деякий час, щоб навчитися створювати наступний впливовий, потужний, впорядкований та важливий веб -додаток, веб -сайт, який все є на вас і робить саме те, що ви хочете, і відповідає потребам вашої аудиторії. Про мене: Я розробник програмного забезпечення з широкимAnge досвіду в C/C ++, Java, Python, HTML, CSS та JavaScript. Я будую веб -сайти, які люди хочуть користуватися, хочуть відвідати і навіть пристрастився до використання просто для того, щоб дізнатися, відтворити та вбивати час, а головне, я продаю програмне забезпечення. Якщо у вас було уявлення про те, як ви хотіли, щоб веб -сайт виглядав і функціонував, ви готові підтримати мене, щоб я міг задовольнити власні потреби, поки я задовольняю ваші, і ви готові покрити витрати на запуску веб -сайту самостійно, Я б створив вам наступний YouTube, Tiktok, Twitter, Google, або навіть високотехнологічний додаток для безпеки лише ви можете отримати доступ. Замість того, щоб намагатися продати вам свій час, я намагаюся купити ваш: я хочу поговорити з вами, щоб створити програму (веб -сайт) сам з такою існує інформація, і навчити вас, що вам потрібно, щоб бути незалежним розробником програмного забезпечення, Підприємець, що веде успішну кар'єру в будь -якій галузі, яку ви бажаєте. І дозвольте мені бути зрозумілим, освіта, яку я даю вам, буде неофіційною. Ви могли б піти до школи і дізнатися все це за допомогоюОсвіта, або навіть прочитайте цю книгу в школі, виконайте свої завдання та забирайте велику справу від вашої освіти, але я офіційно не поставлю вас на гаряче місце і попрошу вас виконати завдання. Я не твій професор, ти можеш подумати про мене, як про друга, який хоче спрямувати тебе до кар’єри, керованої вашим особистим успіхом. І я також не продаю вам успіх, вам потрібно буде купувати його у свій час. Навчання коду має круту криву навчання і ніколи не було легким або навіть не було. Вам потрібно працювати так сильно, як можливо, і продовжувати намагатися провалитись і спробувати ще раз, навіть коли ви розчаровані, щоб вивчити та створити програми самостійно. Це в природі самого коду. Код працює компілятором, який призначений для надання повідомлень про помилки програміста, і вони навчать вас кодувати, навіть якщо ви просто скопіюєте помилку у свою пошукову систему та читаєте приклади інших людей. І я мушу сказати, що вам не потрібно бути надзвичайно багатим, розумним, успішним,en деталі, орієнтовані або організовані для створення програми. Комп'ютер піклується про цю організацію за вас. Вам просто потрібно наполягати на спробах та помилках, підтримувати фокус і наполегливо працювати над тим, що ви робите, і у вас буде дуже успішна кар’єра в цілому того, що робите. Хто я: Я усвідомлюю, що останній розділ був більше про навчання та ваші шляхи з цієї книги. Хто я саме? Це складне питання. Я сам про це незрозумілий, оскільки я страждаю від медичних станів, які можуть ускладнити мені навіть кодувати або писати цю книгу, при цьому представляючи проблеми з соціалізацією та питаннями ідентичності, які ускладнюють моє життя, коли справа доходить до представлення себе . Коротше кажучи, якщо ви читаєте цю книгу, ви привезли її додому, тому що ви пролетіли через неї і подумали, що це корисно, або навіть якщо ви просто прочитали це далеко, для вас я схожа людина, яка хоче бачити, як ви досягаєте успіху все, що ти робиш. Я сам інженер, програмне забезпеченняРозробник та студент, і я пишу цю книгу для інших студентів, які хочуть полегшити своє життя, маючи посібник із програмного забезпечення, яке їм потрібно полегшити своє життя, наводячи приклади, щоб скопіювати, що підходять разом, як велика головоломка в роботу , Корисний, великий, функціональний, згуртований та залучений додаток, який може досягти успіху незалежно від лінійки бізнесу. Багато в чому це я роблю: я будую програми, щоб допомогти собі та іншим людям досягти успіху. Я також автор, хоча це моя перша публікація, яку я маю намір завершити, щоб скласти своє портфоліо в корисний документ, а також художник. Я визнаю це тобі, я начебто дивна людина. Я не ідеальний, я керував законом, навіть змусив мене залишити коледжі та університетів і залишити держави, щоб спробувати зробити собі ім'я з більшим успіхом. Я за народженням жінка, я ношу макіяж, сфотографую себе, ношу сукні та інший жіночий одяг, і я залишаюсь усвідомленим якЧоловік за своєю природою. У мене були проблеми з іншими людьми в минулому, які призводять до боротьби з написанням та створенням WebApps, і я перепрошую, що мені не вдалося швидше дістати цю книгу в руки: вам це було потрібно. Ви захочете прочитати і написати код, схожий на мій, і працює як моє, і робить те саме, але ще краще, бо якщо ви можете дозволити собі придбати цю книгу замість того Для цього у вас є ресурси, необхідні для успіху у своєму житті. У мене були всілякі проблеми з ростом сім'ї, станами здоров'я, лікарями, засобами масової інформації та законом, і мій код глибоко відображає боротьбу, яка є фемінізмом та жіночою природою у розділеному та розчарованому світі. Однак ця книга - це те, про що я глибоко дбаю, моя дитина, моє портфоліо та засоби для існування, тому я ціную ваш розгляд, коли ви візьмете текст додому і ретельно порите над нею, щоб навчитися у мене. Будь ласка, майте на увазі, що я не ідеальний,У книзі будуть помилки, зміни та нові видання, і вам потрібно буде подумати з вашим логічним мозком якнайкраще, щоб мати успішний досвід мого написання. Крім того, зрозумійте, що я маю на увазі для вас, навіть коли ви стикаєтесь з викликами під час написання. Подумайте про це так: Коли ви можете просто взяти напрокат комп'ютерну систему, щоб зробити все, що можна уявити в цифровому просторі, зберігати всю інформацію, з якою ви стикаєтесь, #$%! Yze і організуйте її, і зрозумієте, ви будете Неминуче стикається з труднощами з інформацією, яку ви приймаєте та навіть публікуєте. Я вам це кажу, бо стикаюся з тими ж труднощами. Використовуйте цю книгу на власний ризик, працюйте зі своєю спільнотою та спільнотами, доступними для вас, щоб створити програмне забезпечення в безпечній обстановці, і не сприймайте речі особисто, коли ви не зможете або навіть не вдаєтесь неправильно: ось так я дістався так далеко і чому я можу принести вам цей текст і допомогти вам досягти успіху, не розходячись на шляху божевілля, який відходитьЯ зруйнував, розірвав і побив, поки я стикаюся з звичайними проблемами, які всі роблять у глобальному масштабі завдяки паралелістичному глобальному масштабі мережі, на якій ми будемо працювати, Інтернет. Ви, можливо, не дуже знайомі з тим, ким я є лише з кількома словами, але я закликаю вас читати далі, ви познайомитесь з мною, коли продовжуєте читати та розуміти мене, будуючи власні проекти, щоб завершити свою роботу. Не буде домашнього завдання з цією книгою, доки ваші професори чи викладачі не призначають вам, але я дуже рекомендую вам створити портфоліо проектів самостійно, як ви читаєте, а також проект Capstone, що демонструє, як ви можете Застосовуйте те, що ви дізналися. Мій проект Capstone - це основа для більшості того, що ви прочитаєте в цій книзі, оскільки він включає код з моїх попередніх проектів, код, який я створив, і навчився писати методично вручну, а також широкий спектр ідей та порад, які допомогли мені досягти того, що я можу скрутити просту програму, яка єUlle представлений і виглядає і поводиться як популярний додаток, який ви можете побачити, як ваш друг чи сім'я використовує, в Інтернеті, рекламується до вас чи в новинах. Що таке книга: Ця книга - це підручник за прикладом. Тут ви можете знайти код, інструкції щодо того, як навчитися коду, інформація про код налагодження та виправлення помилок, кроки усунення несправностей, інструкції щодо створення резервного копіювання та збереження коду, повторного розгортання, якщо хтось порушує ваш код, захищає ваш код, розгортання Ваш код, створюйте інтерактивні веб -сайти, які розважають, залучають та звикають, і ви отримаєте відчуття того, хто я, чому це важливо, і як зобразити себе, імідж свого додатка та компанії, а також програмне забезпечення, яке ви будуєте У абсолютному найкращому світлі, щоб бути найбільш привабливим для ваших кінцевих користувачів, відвідувачів вашого веб -сайту. У цій книзі я продемонструю ряд прикладів дизайну програмного забезпечення з акцентом на Інтернет як платформу, а також безпеку. Ми ініціюємо досвід навчання, будуючи базовийECT за допомог...
Практичне веб-поглиблене навчання та безпека на прикладі

Практичне в Інтернеті глибоке навчання та безпека на прикладі Третє видання Шарлотта Харпер 3 липня 2024 року Передмова: Міркування щодо безпеки у створенні програмного забезпечення для Інтернету є важливою частиною плану та виконання будь -якого веб -розробника, а також інженерія прототипу, який є надійним, стабільним та корисним для практичних цілей. DOM (розмітка об'єктів документа), з його реалізацією HTML, JavaScrip Творчість, забезпечуйте простоту використання та функціональності, зображуйте смирення та характер та забезпечуйте простоту використання, а також зручність та важливі послуги, які всі привабливі для середнього Джо, кінцевого користувача, який прагне вбити час або щось зробити в Інтернеті, Зазвичай на пристрої смартфона сенсорного екрану. Більшість людей навіть не знали, з чого почати, коли хочуть створити веб -сайтСкретч, вони, як правило, починаються на веб -сайті іншої людини та створюють щось обмежене у функціональності, надійності, простоті використання та особливо творчості, коли вони могли мати у своєму розпорядженні всі останні потужні інструменти, щоб побудувати щось корисне, не витрачаючи часу на натискання кнопок , особливо витрачаючи гроші на оплату дорогих підписки на програмне забезпечення, які мало хто хотів використовувати, враховуючи, що обмеження в просторі використання та гнучкості. Якщо у вас є кілька хвилин, щоб прочитати цю книгу і дізнатися, чого я хочу навчити вас, або навіть особисто поговорити зі мною про ваші цілі та отримати певні вказівки в правильному напрямку, і мотивовані навчитися кодувати та писати власне програмне забезпечення , Візьміть цю книгу додому і відкладіть деякий час, щоб навчитися створювати наступний впливовий, потужний, впорядкований та важливий веб -додаток, веб -сайт, який все є на вас і робить саме те, що ви хочете, і відповідає потребам вашої аудиторії. Про мене: Я розробник програмного забезпеченняДіапазон досвіду в C/C ++, Java, Python, HTML, CSS та JavaScript. Я будую веб -сайти, які люди хочуть користуватися, хочуть відвідати і навіть пристрастився до використання просто для того, щоб дізнатися, відтворити та вбивати час, а головне, я продаю програмне забезпечення. Якщо у вас було уявлення про те, як ви хотіли, щоб веб -сайт виглядав і функціонував, ви готові підтримати мене, щоб я міг задовольнити власні потреби, поки я задовольняю ваші, і ви готові покрити витрати на запуску веб -сайту самостійно, Я б створив вам наступний YouTube, Tiktok, Twitter, Google, або навіть високотехнологічний додаток для безпеки лише ви можете отримати доступ. Замість того, щоб намагатися продати вам свій час, я намагаюся купити ваш: я хочу поговорити з вами, щоб створити програму (веб -сайт) сам з такою існує інформація, і навчити вас, що вам потрібно, щоб бути незалежним розробником програмного забезпечення, Підприємець, що веде успішну кар'єру в будь -якій галузі, яку ви бажаєте. І дозвольте мені бути зрозумілим, освіта, яку я даю вам, буде неофіційною. Ви могли б піти до школи і дізнатися все це за допомогоюОфіційна освіта, або навіть прочитайте цю книгу в школі, виконайте свої завдання та забирайте велику справу від вашої освіти, але я офіційно не поставлю вас на гаряче місце і попрошу вас виконати завдання. Я не твій професор, ти можеш подумати про мене, як про друга, який хоче спрямувати тебе до кар’єри, керованої вашим особистим успіхом. І я також не продаю вам успіх, вам потрібно буде купувати його у свій час. Навчання коду має круту криву навчання і ніколи не було легким або навіть не було. Вам потрібно працювати так сильно, як можливо, і продовжувати намагатися провалитись і спробувати ще раз, навіть коли ви розчаровані, щоб вивчити та створити програми самостійно. Це в природі самого коду. Код працює компілятором, який призначений для надання повідомлень про помилки програміста, і вони навчать вас кодувати, навіть якщо ви просто скопіюєте помилку у свою пошукову систему та читаєте приклади інших людей. І я мушу сказати, що вам не потрібно бути надзвичайно багатим, розумним,Есфули або навіть деталі, орієнтовані або організовані для створення програми. Комп'ютер піклується про цю організацію за вас. Вам просто потрібно наполягати на спробах та помилках, підтримувати фокус і наполегливо працювати над тим, що ви робите, і у вас буде дуже успішна кар’єра в цілому того, що робите. Хто я: Я усвідомлюю, що останній розділ був більше про навчання та ваші шляхи з цієї книги. Хто я саме? Це складне питання. Я сам про це незрозумілий, оскільки я страждаю від медичних станів, які можуть ускладнити мені навіть кодувати або писати цю книгу, при цьому представляючи проблеми з соціалізацією та питаннями ідентичності, які ускладнюють моє життя, коли справа доходить до представлення себе . Коротше кажучи, якщо ви читаєте цю книгу, ви привезли її додому, тому що ви пролетіли через неї і подумали, що це корисно, або навіть якщо ви просто прочитали це далеко, для вас я схожа людина, яка хоче бачити, як ви досягаєте успіху все, що ти робиш. Я сам інженер,Розробник та студент, і я пишу цю книгу для інших студентів, які хочуть полегшити своє життя, маючи посібник із програмного забезпечення, яке їм потрібно полегшити своє життя, наводячи приклади, щоб скопіювати, що підходять разом, як велика головоломка в роботу , Корисний, великий, функціональний, згуртований та залучений додаток, який може досягти успіху незалежно від лінійки бізнесу. Багато в чому це я роблю: я будую програми, щоб допомогти собі та іншим людям досягти успіху. Я також автор, хоча це моя перша публікація, яку я маю намір завершити, щоб скласти своє портфоліо в корисний документ, а також художник. Я визнаю це тобі, я начебто дивна людина. Я не ідеальний, я керував законом, навіть змусив мене залишити коледжі та університетів і залишити держави, щоб спробувати зробити собі ім'я з більшим успіхом. Я за народженням жінка, я ношу макіяж, сфотографую себе, ношу сукні та інший жіночий одяг, і я залишаюсь усвідомленим якЖіноча за своєю природою. У мене були проблеми з іншими людьми в минулому, які призводять до боротьби з написанням та створенням WebApps, і я перепрошую, що мені не вдалося швидше дістати цю книгу в руки: вам це було потрібно. Ви захочете прочитати і написати код, схожий на мій, і працює як моє, і робить те саме, але ще краще, бо якщо ви можете дозволити собі придбати цю книгу замість того Для цього у вас є ресурси, необхідні для успіху у своєму житті. У мене були всілякі проблеми з ростом сім'ї, станами здоров'я, лікарями, засобами масової інформації та законом, і мій код глибоко відображає боротьбу, яка є фемінізмом та жіночою природою у розділеному та розчарованому світі. Однак ця книга - це те, про що я глибоко дбаю, моя дитина, моє портфоліо та засоби для існування, тому я ціную ваш розгляд, коли ви візьмете текст додому і ретельно порите над нею, щоб навчитися у мене. Будь ласка, майте на увазі, що я ніЕкт, у цій книзі будуть помилки, перегляди та нові видання, і вам потрібно буде подумати з вашим логічним мозком якнайкраще, щоб мати успішний досвід мого написання. Крім того, зрозумійте, що я маю на увазі для вас, навіть коли ви стикаєтесь з викликами під час написання. Подумайте про це так: Коли ви можете просто взяти напрокат комп'ютерну систему, щоб зробити все, що можна уявити в цифровому просторі, зберігати всю інформацію, з якою ви стикаєтесь, #$%! Yze і організуйте її, і зрозумієте, ви будете Неминуче стикається з труднощами з інформацією, яку ви приймаєте та навіть публікуєте. Я вам це кажу, бо стикаюся з тими ж труднощами. Використовуйте цю книгу на власний ризик, працюйте зі своєю спільнотою та спільнотами, доступними для вас, щоб створити програмне забезпечення в безпечній обстановці, і не сприймайте речі особисто, коли ви не зможете або навіть не вдаєтесь неправильно: ось так я дістався так далеко і чому я можу принести вам цей текст і допомогти вам досягти успіху, не розходячись на шляху божевілляAves Me Roos, розірваний і побив, поки я стикаюся з звичайними проблемами, які кожен робить у глобальному масштабі завдяки паралелістичному глобальному масштабі мережі, на якій ми будемо працювати, Інтернет. Ви, можливо, не дуже знайомі з тим, ким я є лише з кількома словами, але я закликаю вас читати далі, ви познайомитесь з мною, коли продовжуєте читати та розуміти мене, будуючи власні проекти, щоб завершити свою роботу. Не буде домашнього завдання з цією книгою, доки ваші професори чи викладачі не призначають вам, але я дуже рекомендую вам створити портфоліо проектів самостійно, як ви читаєте, а також проект Capstone, що демонструє, як ви можете Застосовуйте те, що ви дізналися. Мій проект Capstone - це основа для більшості того, що ви прочитаєте в цій книзі, оскільки він включає код з моїх попередніх проектів, код, який я створив, і навчився писати методично вручну, а також широкий спектр ідей та порад, які допомогли мені досягти того моменту, коли я можу скрутити просту програму, якаПовністю представлений і виглядає та поводиться як популярний додаток, який ви можете побачити, як ваш друг чи сім'я використовує в Інтернеті, рекламується до вас чи в новинах. Що таке книга: Ця книга - це підручник за прикладом. Тут ви можете знайти код, інструкції щодо того, як навчитися коду, інформація про код налагодження та виправлення помилок, кроки усунення несправностей, інструкції щодо створення резервного копіювання та збереження коду, повторного розгортання, якщо хтось порушує ваш код, захищає ваш код, розгортання Ваш код, створюйте інтерактивні веб -сайти, які розважають, залучають та звикають, і ви отримаєте відчуття того, хто я, чому це важливо, і як зобразити себе, імідж свого додатка та компанії, а також програмне забезпечення, яке ви будуєте У абсолютному найкращому світлі, щоб бути найбільш привабливим для ваших кінцевих користувачів, відвідувачів вашого веб -сайту. У цій книзі я продемонструю ряд прикладів дизайну програмного забезпечення з акцентом на Інтернет як платформу, а також безпеку. Ми ініціюємо досвід навчання, будуючи базовийOject за допомогою оболонки Unix, з функціями резервного копіювання та сценаріїв. Потім ми розглянемо базовий веб -сайт блогу, оновіть наш блог за допомогою функцій фото та відео, а також використовувати ці функції для використання рішень безпеки за допомогою безкоштовного програмного забезпечення та захищає наш сервер за допомогою модуля аутентифікації, що підключається (PAM). Потім ми розглянемо обробку та обробку файлів, вивчення редагування відео, пожертвування голосу, сканування штрих -коду та розпізнавання оптичного характеру серед інших понять. По дорозі ми розглянемо API, які допоможуть нам зробити наше програмне забезпечення більш корисним та безпечним, з безкоштовними та платними варіантами. По дорозі ми вивчимо інструменти для фізичної безпеки та войовничих виробів, такі як вогнепальна зброя та боєприпаси, що проектують та виготовляють, включаючи дизайн ствола та ретранслятора, дизайн башточок та безпілотників та інші принципи, які ми інтегруємо з нашим програмним забезпеченням у існуючій мережі, щоб захистити наше програмне забезпечення і продемонструвати самооборону та стійкість. Ми зробимо перерви на шляху до побудови ігор, 2D та 3DДвигуни, що надають, і працюють із вбудованим обладнанням у прикладах дослідження базового розміру програмного забезпечення та електронного вібраційного масажера, що відливаються в силіконовому гумі відповідно. Попутно ми також будемо використовувати вже доступні рішення машинного навчання, щоб краще забезпечити наше програмне забезпечення. Ми також використовуватимемо інструменти для акцій, доступні для Інтернету, щоб впорядкувати та забезпечити процес. Ця книга - це посібник з вашого успіху у створенні веб -додатку та інтеграції її з професійною мережею комп'ютерних та вбудованих механічних систем, а в цілому - посібником з будівництва програмного забезпечення та вбудованого обладнання без фонового знання чи попереднього досвіду. Що це за книга: Якщо ви дійсно хочете мати веб -сайт, ви можете просто налаштувати простий магазин і продати те, що вам потрібно, опублікувати блог, опублікувати фотографії чи відео чи іншим чином, не пишучи жодного рядка коду. Ця книга - це не така. Ця книга навчить вас будувати програмне забезпечення, яке є більш корисним, повністюЗапропоноване, функціональне та безпечне, ніж будь -яке програмне забезпечення, яке ви вже можете знайти, оскільки воно розгортає останнє програмне забезпечення, яке все ще є прототипами, може бути дорогим для роботи в масштабах, які працюють старші компанії, і не звертаються до зворотних, заплутаних компаній, створених Заробляйте гроші на людей, які насправді нічого не роблять. Якщо ви уважно дотримуєтесь цієї книги, ви хочете написати код, код дослідження, створити власні програми, і ви заробляєте гроші з того, що робите. Я зароблю гроші з цієї книги навіть на ранніх стадіях, оскільки вона містить інформацію, яку люди потребують і хочуть читати, і вже купують, коли вони купують або використовують мої програми. Ця книга не створить для вас додаток, але вона буде вказувати вам у правильному напрямку та озброїть вам потрібні інструменти та навички та поради, які сприятимуть вашому власному успіху в створенні програмного забезпечення для Інтернету з кожним рядком код, який вам потрібно буде написати як приклад, готовий до складання разом у програмне забезпечення, яке ви та ваші прихильники, гості, клієнтура,Ріанди, сім'я, відвідувачі, підрядники та люди Інтернету хочуть використовувати та підтримувати. Що ви дізнаєтесь: Ця книга навчить вас будувати та продавати програмне забезпечення, дійсно функціональне, корисне програмне забезпечення, медіа -запис, такі функції безпеки, такі як розпізнавання обличчя, сканування штрих -коду з читабельним машинами, веб -API для аутентифікації, запису та надання відео та фотографій та обміну повідомленнями Bluetooth і поблизу поля (NFC) спілкування. Ця книга навчить вас використовувати мережевий комп'ютер, зосередившись на Debian Linux, як створити код Bash, щоб зробити встановлення та резервне копіювання вашого програмного забезпечення безшовним, автоматизованим вітерцем, як створити код Python як бекенд для обслуговування динамічних повідомлень, стилю Речі красиво використовують стилі CSS з Bootstrap, увімкнути входи користувачів та інтерактивність за допомогою мережевих пристроїв, створити інтерактивні медіа та мережу з іншими веб -сайтами, щоб запропонувати функції безпеки, такі як текстові повідомлення для перевірки чи інших цілей, сканування ідентифікаторів, модеру зображення та відео, даніРансакції, щоб захистити ваше програмне забезпечення, обробка платежів, торгівля криптовалютами, асинхронні завдання тощо. Ви дізнаєтесь, як будувати власні пристрої Bluetooth, з акумуляторами, зарядними пристроями, мікроконтролами, ланцюгами, двигунами та датчиками, використовуючи припою, дріт та 3D -надруковані, а також литі матеріали. Я продемонструватиму основних директорів 3D -дизайну, застосованих до виробництва добавок та інструментів та виготовлення штампів, тому ви зможете виготовити власні вбудовані, апаратні пристрої з інтегрованими батареями, зарядними пристроями, електронними схемами та функціональними виходами. і налагодити їх за допомогою Bluetooth та Інтернету. Зокрема, ми розглянемо два тематичні дослідження, вібруючий масажер та домашню вогнепальну зброю, обидва запрограмовані в OpenScad, який доступний як графічний інтерфейс або утиліта командного рядка і може бути інтегрована в Інтернет для більш швидких результатів. Ви дізнаєтесь, як будувати та розгорнути веб -сайт з нуля без попереднього досвіду, робити його функціональним, безпечним, красивим, кориснимПрактично практично. Ви дізнаєтесь, як використовувати машинне навчання та комп'ютерне бачення, щоб зробити сайт захищеним та більш практичним, записуйте відео та аудіо з вашого веб -сайту, пожертвуйте голос, створюйте музику та модулюйте аудіо, щоб створити корисні зразки та як пробити шум Використання інших веб -сайтів для створення найкращої можливої ​​мережі веб -сайтів, яку ви можете зв’язати безпосередньо з вашим, щоб поділитися всією корисною інформацією, яку ви можете запропонувати, і ще важливіше принести людей до вашого програмного забезпечення та бізнесу. Ця книга буде зосереджена найбільше на медіа, безпеці та машинному навчанні, які є основними трьома компонентами, які допоможуть вам створити корисне програмне забезпечення для Інтернету, залучаючи правильних користувачів та відключили неправильні способи, що є реалістичним, практичним, Руки та залучення, а також автоматичний, і міцний. Ця книга вчить Unix, зокрема Debian (Ubuntu), Bash Shell, Python, HTML, CSS, JavaScript та ряд корисних програмних пакетів дляn, як запити, а також корисне програмне забезпечення Bash, як Git та FFMPEG. Я також навчу вас автоматично торгувати криптовалютою та приймати платежі в криптовалюті або з регулярних дебетових карток, навіть виплачуючи відвідувачам частку вашого доходу, якщо ви вирішите це зробити. Я навчу вас заробляти гроші на своєму веб -сайті за допомогою реклами, як підготувати свою програму для пошукових систем і зробити його швидким, займає перше рейтинг за тим, що ваші клієнти будуть шукати, щоб знайти вас, і рейтинг стільки поширених пошуки якомога більше. Я навчу вас продавати своє програмне забезпечення, рекламувати його, звертатися до клієнтів, які шукають ваші послуги, та зробіть ім’я в Інтернеті через шляхи, які вже існують, є недорогими та добре працюють. Я навчу вас, як зберегти свої дані на хмарних комп'ютерах, які працюють для вас, і дешево зберегти ваші дані, як планувати та створити веб -сайт, який робить те, що хочуть ваші користувачі та що ви хочете, і як тримати своїх користувачівВзявши свій сайт, натисніть на їхні телефони з сповіщеннями, електронною поштою, текстовими повідомленнями, телефонними дзвінками та більшою кількістю шляхів, щоб повернути своїх користувачів на ваш веб -сайт у вашому розпорядженні за натисканням кнопки, захищеної лише від вас. Ця книга буде зосереджена на практичній публікації та розповсюдженню ЗМІ у великих кількостях, від тексту до фотографій до відео до аудіо, справляючи гарне враження для кінцевих користувачів (вашої клієнтури) та продавати себе будь -яким способом, щоб створити, щоб створити Веб -сайт, додаток, який є представником для вас і ви тільки, і змушує вас, ваше програмне забезпечення та ваша компанія виглядають добре найкращим чином. Ви також дізнаєтесь у мене кілька порад та рекомендацій, від поради щодо кодування, практичної марнославства, таких як макіяж та фотографія, моделювання та акторська майстерність тощо для вас, розповсюджуючи стільки вмісту, скільки вам потрібно в здоровому балансі платформ, щоб принести вашe до плодів, не маючи більше зусиль, роботи чи грошей, ніж це необхідно. Ця книга називається «Практичне в Інтернеті глибоке навчання та безпека за прикладом» з причини: вона стосується навчання коду, зокрема для Інтернету, зокрема з акцентом на безпеку, з практичної точки зору, з прикладами робочого коду, який служить Практичні цілі, викладені в тексті. Навчальний компонент цього тексту також охоплює машинне навчання, код, який я покажу вам, як запустити в Інтернеті, яка буде обробляти комп'ютерне зору, розпізнавання обличчя, модерацію зображення та відео, вдосконалення зображень, вдосконалення роздільної здатності, підписи зображень та інші завдання Показники прогнозування отримані із зображень, таких як природа зображення як справжнє, комп'ютерне зображення, або оптична копія (фотографія зображення або друкована фотографія). Машинне навчання є дуже важливим, коли мова йде про безпеку веб -безпеки та програмного забезпечення, оскільки воно може виконувати завдання, які інакше були неможливими. Ваш комп’ютерУвійдіть за допомогою парольного коду, але може бути безпечніше використовувати його, якщо він входить у вас обличчям. Ви можете зробити серверний комп'ютер таким безпечним, комп'ютером, який зазвичай просить вас про ім’я користувача та пароль і ввійти у вас, можливо, з маркером підтвердження для кожного нового входу або нової IP -адреси, але якщо ви будуєте великі масштаби, простий у Використання, принципово безпечне та потужне програмне забезпечення, цього може бути достатньо. Занадто уважно прив’язати своє програмне забезпечення до чужого програмного забезпечення, наприклад, послуги електронної пошти або послуги текстових повідомлень, недостатньо, щоб зробити ваше програмне забезпечення безпечним або чиїсь (будь -який сайт, який ви використовуєте). Кожен, хто будує програмне забезпечення, яке бездоганно захищає, має певне розуміння того, що це означає. Програмне забезпечення за своєю суттю невпевнено, оскільки пристрої та облікові записи, які ми використовуємо для доступу до нього, не завжди є в нашому розпорядженні, вони можуть бути в руках тих, хто має намір для програмного забезпечення, і тому можуть становити ризик для самого програмного забезпечення. Це щось у фокусі цієї книги. Мережевий комп'ютер за замовчуваннямЗабезпечений довгим ключовим маркером, який називається та SSH або захищеним ключем оболонки, і в іншому випадку найкраще забезпечений веб -сервером, оскільки веб -сервер забезпечує відкритий доступ, а також сучасні інструменти безпеки, що працюють на самому сервері. Веб -сервер має доступ до веб -браузера користувача, який, мабуть, є найпотужнішою частиною пристрою користувача, оскільки це місце, де користувач може отримати доступ до мережевого програмного забезпечення. Цей інструментарій може відображати текст, веб -сторінки, які ви бачите, а також можуть записувати зображення, аудіо та відео (наприклад, фотографія обличчя або ідентифікатора стану), може читати та записувати на радіопристрої Bluetooth, і може читати та записувати в поле поля Теги TransPonder, недорогі ключові картки, FOBS, наклейки, кільця та навіть чіп -імплантати з унікальними серійними номерами, які можна читати та записати за допомогою даних, створених та підтверджених веб -сервером, прив’язаним до веб -сайту. Використовуючи всі інструменти у вашому розпорядженні, за допомогою цієї книги ви оснащете себе знаннями, щоб створити безпечний веб -сайт та загалом aКомп'ютерна система URE, яка працює для вас, робить ваші торги, виглядає і відчуває себе правильно. З чого почати: Ви можете пропустити повз розділ, я починаю цю книгу або будь -який розділ, до того, що вам потрібно, особливо якщо у вас є досвід кодування до або будь -якого з вищезгаданих інструментів, які я детально описую в цій книзі як а також документування випадків використання та практичних прикладів. Якщо у вас немає досвіду написання коду, я настійно рекомендую прочитати всю цю книгу, і особливо рекомендую прочитати попередні розділи, щоб переконатися, що ця книга підходить саме вам. Якщо ця книга не підходить для вас, подумайте про те Вчитель чи інші вчителі зробили переді мною. Почніть, де ви хочете, кожна частина цієї книги буде корисною, якщо ви маєте намір створити кориснуPP, і вважайте, що найкращі програми побудовані з урахуванням кінцевого користувача: знайте свого клієнта. Тепер ви знаєте мене, знаєте цю книгу, і ви готові розпочати. Для початку візьміть комп'ютер (навіть найдешевший ноутбук із магазину коробки, Amazon або старий робочий стіл працює, і налаштуйте його таким чином, що працює для вас. Як читати цю книгу: Виділений текст, позначає, що текст належить до командного рядка, де ви напишете код, який ви запускаєте. Командний рядок сильно орієнтований на клавіатуру і вимагає мало клацання, прискорюючи свій робочий процес та полегшуючи вам речі. Початок роботи: Давайте зануримось. Ми почнемо з побудови коду на місцевій машині та почнемо без створення веб -сайту, підключеного до Інтернету. Це безпечніше, щоб почати, нічого не коштує, і вам легко. Залежно від вашої операційної системи, потрапляння в оболонку баш буде трохи інакше. Для ОС Mac я рекомендую встановити віртуальну машину в цей момент, оскільки ви отримаєте найбільш сумісністьВіртуальна машина. Різні постачальники, такі як VirtualBox та Paralells, можуть запустити для вас віртуальну машину, хоча також можна встановити Ubuntu безпосередньо на машині, якщо ви вважаєте за краще використовувати рідне середовище, яке рекомендується для створення швидкого, обтічного досвіду. Якщо ви використовуєте Linux або Windows, які я рекомендую, створити проект це повинно бути досить просто. Відкрийте термінал, відрегулюйте розмір, як вважаєте за потрібне, і почніть наступний крок 2. Якщо ви використовуєте Windows, будь ласка, дотримуйтесь кроку 1. Крок 1: - Тільки користувачі Windows У Windows відкрийте командний рядок як адміністратор та введіть WSL - ВІДПОВІДЬ Крок 2: - Продовжуйте тут, або пропустіть крок 1 до тут, якщо ви не використовуєте Windows У відкритому терміналі (залежно від вашої ОС, що називається Ubuntu у Windows, термінал у Mac або Linux, або подібне ім'я), почніть із створення проекту. Ми робимо це за допомогою команди MKDIR, яка створює каталог. Якщо вам потрібно створити каталог для зберігання проекту, який рекомендується, використовуйтеКоманда CD для зміни каталогу та та CD/PATH/TO/каталог - Шлях - це папки (файли), які передують каталогу призначення, ваш шлях за замовчуванням - ~ або/домашнє/користувача (де ім'я користувача - ваше ім'я користувача). Щоб змінити каталог за замовчуванням, введіть CD або CD ~ Приклад MKDIR - Замініть "Приклад" назвою каталогу Тепер у вас є робочий каталог для вашого проекту. Будучи так важливо зберегти цей каталог, якщо вам потрібно перейти на іншу машину або розгорнути код, який ви пишете, щоб він був готовий до Інтернету, ми створимо сценарій, щоб створити резервну копію вашого каталогу в найближчі кілька кроків. Але побудова сценарію потребує трохи коду, і код повинен бути автоматизований, щоб бути максимально корисним. Тож давайте побудуємо сценарій, щоб спочатку побудувати сценарії. Почнемо зі створення сценарію та зробимо його виконуваним. Ми використовуємо для цього sudo, chmod та дотик, і зателефонуємо до сценарію


sudo touch /usr/bin/ascript
sudo chmod a+x /usr/bin/ascript
sudo nano /usr/bin/ascript
Тепер ми створили сценарій, зробили його виконуваним і готовим редагувати його. Nano - це текстовий редактор, який дозволить вам редагувати текст без натискання, що набагато простіше, ніж використання графічного інтерфейсу користувача. Щоб відредагувати файл з Nano, використовуйте Nano, а потім шлях до файлу. Щоб зробити сценарій, який робить сценарій, він досить схожий на те, щоб зробити наш сценарій в першу чергу. Ми використовуємо той самий код, що і вище, замінюючи назву сценарію, "ASCRIPT" параметром аргументу, $ 1. Це дозволяє нам зателефонувати до сценарію, ввівши просто Sudo Ascript Newscript, і в цей момент ми можемо створити будь -який новий сценарій, замінивши "Newscript" на ім'я вашого сценарію. Код у нано повинен виглядати:

sudo touch /usr/bin/$1
sudo chmod a+x /usr/bin/$1
sudo nano /usr/bin/$1
І щоб закрити Nano, ми можемо утримувати клавішу управління і натиснути X, а потім Y, щоб позначити, що ми зберігаємо файл, і натиснуте на повернення. Тепер замість того, щоб вводити ці три команди для редагування сценарію, ми зможемо ввести Sudo Ascript Ascript, щоб знову редагувати сценарій. Це працює! І будь -який новий сценарій можна легко запустити, викликаючи його в оболонку. Давайте збережемо нашу роботу зараз: Давайте напишемо сценарій резервного копіювання, щоб зберегти наш новий сценарій, а потім створили резервну копію в нашому каталозі проекту, а також створимо резервну копію сценарію резервного копіювання.

sudo ascript backup
Тепер, в Нано:

sudo cp /usr/bin/backup /path/to/directory/
sudo cp /usr/bin/ascript /path/to/directory/
Де/шлях/до/каталог - це шлях до проекту, який ви створили за допомогою MKDIR. Пізніше ми дізнаємось, як копіювати подібні повторні шляхи за допомогою циклу та списку, що менше коду, але поки що давайте простіше і матимемо кілька рядків. Щоб запустити цей сценарій та створити резервну копію коду, збережіть файл у Nano за допомогою Control+x, y та поверніться, і введіть нижче у свою оболонку

backup
Якщо вам взагалі буде запропоновано пароль під час читання цієї книги та слідкуючи за оболонкою, будь ласка, введіть пароль користувача правильно, у вас будуть три спроби, перш ніж вам потрібно повторно запустити команду. Ви можете використовувати стрілки вгору та вниз, щоб повторно їх та редагувати, якщо вам потрібно запустити що -небудь двічі. Прості натискання вгору та вниз, щоб вибрати команду, перш ніж редагувати команду правою, лівою стрілкою та видалити клавішу, а також клавіатуру, і запустити її з поверненням. Вітаємо! Вам вдалося створити дивовижний сценарій резервного копіювання, який підкріплює два важливі сценарії оболонки у вашому робочому каталозі. Ми можемо перемістити речі пізніше, коли проект стає більшим, але це вже працює. Давайте перейдемо до резервного копіювання у хмарі, ми використаємо для цього Github (хоча для резервного копіювання є численні інші рішення GIT, вони все приблизно однакові.) Git - це програмне забезпечення для контролю Verision, яке дозволяє створити резервні копії до вашого Програмне забезпечення, коли ви робите їх на сервер, покиТакож дозволяючи завантажувати цілі копії вашого програмного забезпечення за паролем або ключем. Це сприяє збереженню вашого програмного забезпечення, тим більше, що ми переходимо до захищених екземплярів Linux, які іноді розбиваються, коли один рядок коду не виходить з ладу, залишаючи вас заблокованими, поки ваш код може не бути резервним копією, якщо ви не отримаєте шансів повернути підтримку Вгору автоматично, що ми будемо висвітлювати. Якщо ви вже не використовуєте віртуальну машину Ubuntu на даний момент, я рекомендую використовувати віртуальну машину Ubuntu на даний момент, оскільки це полегшить ваше життя при встановленні всіх пакетів, необхідних для створення робочого веб -сайту та заробити глибоке навчання операції на вашому комп’ютері. Ми перенесемо код на веб -сервер найближчим часом, але ми хочемо переконатися, що за нашим веб -сервером є щонайменше кілька шарів безпеки, стійкі до фішингу, і використовуємо ряд пакетів Linux для цього це. Якщо ви все ще хочете використовувати ОС Mac, ви можете шукати та встановитиe необхідні пакети в Інтернеті, але для кожної упаковки, можливо, не буде альтернативи для кожної книги чи серії. Додамо кілька команд, щоб здійснити нашу роботу за допомогою сценарію резервного копіювання, запустивши команду sudo Ascript

# ...
git add –all
git commit -m “backup”
git push -u origin master
Ще раз керувати X, щоб зберегти. Тепер нам потрібно зробити одноразову конфігурацію для цього проекту. Оскільки це незабаром буде проектом 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
Скопіюйте текст, який повертається останньою командою, і створіть обліковий запис у свого постачальника GIT (в ідеалі Github), перш ніж додати ключ SSH до свого облікового запису. Після того, як у вас є обліковий запис, натисніть на верхнє праве меню та введіть налаштування, перш ніж додати клавішу SSH в клавіші SSH та GPG під доступ у меню. Виберіть Додати клавішу SSH та додайте своє, вставивши його та надавши йому назву, перш ніж зберегти та повернутися до Github, щоб створити новий сховище. Це схоже на інших постачальників GIT, вам потрібно буде прочитати їх документацію. У новій конфігурації сховища дайте своєму сховищі описового імені та вирішити, чи хочете ви його опублікувати, і переконайтеся, що ще немає файлів для включення. Після створення сховища скопіюйте клон за допомогою URL -адреси SSH та вставте його в наступну команду.

git remote add git://… (your remote URL)
Тепер ви можете повернутися до свого сховища за допомогою CD, ви будете знайомі з цим. Спробуйте свій резервний сценарій зараз із резервною копією Чудово! Тепер ми можемо дійсно отримати кодування. Давайте встановимо Джанго тепер, коли ми добре зрозуміємо Баш і Гіт. Django дозволить нам автоматично створити резервну копію нашого програмного забезпечення, Bash може це зробити теж, але Django повинен мати більш простішу безпечну реалізацію (його можна відключити та налаштувати легше). Для встановлення програмного забезпечення в Ubuntu ми будемо використовувати команду Sudo Apt-get. По -перше, давайте оновимо та оновимо програмне забезпечення, яке ми вже мали. Це можна зробити за допомогою оновлення Sudo Apt-get та оновлення sudo apt-get -y. Далі, давайте встановимо Python та наше віртуальне середовище, будинок нашого коду, з такою командою: sudo apt-get Встановити python-is-python3 python3-venv Це все, що вам потрібно, щоб піти з Django з точки зору встановлення програмного забезпечення в екземплярі Ubuntu. Для Windows та Linux це має бути досить просто, але для Mac ви можете встановити віртуальну машину таLinux на ньому за допомогою безкоштовного або платного віртуального середовища, наприклад, VirtualBox або Paralells Desktop та відтворити вищезазначені кроки, щоб налаштувати середовище Ubuntu. Ubuntu є критичним у цьому випадку, оскільки це програмне забезпечення, яке працює веб -сайти, і дозволяє їм розміщувати веб -сайти з усім вищезгаданим програмним забезпеченням. Давайте копаємося в Джанго. У нашому каталозі знову, з

python -m venv venv # Створює віртуальне середовище, де зберігається код
source venv/bin/activate # Активує віртуальне середовище
pip install Django
django-admin startproject mysite . # Там, де MySite - це проект, який я починаю в своєму поточному каталозі.
Django просто запускає нас, оскільки Django розміщує веб -сервер і робить все, що потрібно, щоб отримати базовий місцевий веб -сайт. Тепер, коли у нас встановлено Django, давайте трохи редагуємо налаштування, щоб він працював, як нам потрібно. По -перше, давайте створимо новий додаток

python manage.py startapp feed
Ви помітите, що перший додаток називається Feed. Додаток слід називати все, що вам подобається, і ми створимо нові програми, але назва кожного програми повинна бути послідовною щоразу, коли додаток посилається на код. Щоб додати новий додаток, ми завжди будемо редагувати settings.py в іншому каталозі, який створив додаток, названий в додатку StartProject, Aufterfer. Використовуючи нано,

nano app/settings.py
У налаштуваннях знайдіть встановлений_apps та розділіть [] на 3 рядки. Використовуючи чотири простори на порожній центральній лінії, додайте "подачу" або назву вашого додатка. Цей розділ налаштувань.py повинен виглядати:

INSTALLED_APPS = [
    'feed',
]
Перш ніж забути, давайте перевіримо, що Джанго працює. Використовуючи команду Python Manage.py runserver 0.0.0.0:8000, ми можемо запустити сервер, а потім перейти у веб -браузер на комп’ютері, запускаючи код до http: // localhost: 8000 і див. Приклад веб -сторінки (вона працює!) Киньте сервер за допомогою управління C, те саме, що і будь -яка інша команда. Тепер давайте розберемося, щоб написати якийсь код Python. У Джанго є три основні компоненти, усі вони повністю працюють за кодом. Компоненти називаються моделлю, переглядом та шаблоном, і кожен знаходиться на більш високому та нижньому рівні відповідно до доставки веб -сторінки користувачеві. Модель - це код, який зберігає інформацію в базі даних для пошуку, сортування та візуалізації. Вид вирішує, як модель надається, маніпулюється та модифіковано, майже кожен вигляд буде використовувати модель безпосередньо. Шаблон - це HTML -код з деякими додатковими дзвонами та свистами, які називаються мовою шаблону. Шаблон надається видом, де він заповнений кодом Python іТакі контекст, як моделі та інформація (Usuall Strings та цілі числа) з точки зору. У Джанго є й інші компоненти, включаючи, але не обмежуючись ними: Налаштування, які налаштовують додаток, як ми говорили. URL -адреси, які є шаблоном, до яких користувач дотримується, щоб отримати доступ до конкретних частин веб -програми. Форми, які визначають, як інформація, яка надсилається на сервер, обробляється та надається до бази даних, а також користувачеві. Це основа інформації про обробку на стороні сервера і може приймати будь -який тип інформації, яку зберігає комп'ютер, особливо текстові рядки, цифри та справжні/помилкові булеви (зазвичай прапорці). Шаблони, які є HTML -кодом та мовою шаблону, та мостоять розрив між Python та HTML, що означає інформацію про Python, може бути виконаний як HTML -код, до якого кожен може отримати доступ, і може забезпечити веб -сайт з обмеженим доступом, одночасно робить код Python доступним для Інтернету та корисним для різних цілей на віддаленому пристрої, який ніeed бути біля сервера. Статичні файли, які зазвичай є JavaScript, і це бібліотеки, які сервер обслуговує і пов'язаний з шаблоном. Медіа -файли, які сервер обслуговує або проводиться зовні, або просто записується на сервер, перш ніж обробляти та розміщувати на інший сервер (відро) для хостингу. Середнє програмне забезпечення, яке є кодом, які працюють одночасно, як і кожен погляд, і вважаються "включеними" у погляді. Контекстні процесори, які обробляють контекст кожного погляду та використовуються для додавання додаткового контексту. Тести, які підтверджують, що користувач або запит передає певні вимоги до того, як перегляд буде надано. Споживачі, які диктують, як WebSockets обробляють та реагують на спілкування. Адміністратор, який використовується для реєстрації моделей, щоб їх можна було детально маніпулювати на сторінці адміністратора Django, де база даних може бути введена через графічний інтерфейс. Селера, яка визначає асинхронні завдання, частини коду Django можуть розпочатисяНЕПРАВИ ПЕРЕГЛЯДУВАННЯ ПРАВИЛЬНОГО ДО наступного завдання або Рядок коду. Django може мати багато інших компонентів, про які ми детально обговоримо тут. Існує безліч способів зробити Django більш функціональним, додавши Websockets, які є швидкими, впорядкованими каналами зв'язку, селерою, яка виконує асинхронні завдання, і безліч інших програмного забезпечення для розширення django, особливо у функціях перегляду, де більшість із Код виконується. Функції перегляду є ключовими, оскільки вони зазвичай оголошують кожен фрагмент коду, який є специфічним для конкретної схеми URL -адрес або розділу сервера. Спочатку давайте вивчимо функції перегляду. Функції перегляду починаються з імпорту, що позначає код, який буде використаний у перегляді, і визначаються за допомогою регулярних визначень функцій або класів. Найпростіші погляди визначаються визначенням функції DEF та повернути httpression з основним шаблоном. Почнемо з визначення основного подання, щоб повернути текст "Hello World". Пам'ятайте, що кожного разу, коли ви додаєтеЗрозуміло, як DEF, якщо, хоча для тощо, вам потрібно буде додати 4 пробіли для кожного з попередніх визначень, які ви хотіли б застосувати до своєї функції. Ми незабаром увійдемо в те, що кожен із цих означає. З каталогу нашого сайту редагувати файл seed/views.py за допомогою нано та додайте наступні рядки до кінця

from django.http import HttpResponse

def hello(request):
    return HttpResponse('hello world')
HTTPRESSONS Django відповідає текстовим рядком, позначеним відкриттям та закриттям ". Кожен раз, коли ви передаєте інформацію на функцію чи клас, наприклад, запит або рядок, вам потрібно буде використовувати дужки (відкриття та закриття). Це не все, що нам потрібно, щоб побачити наш погляд. Звичайно, ми не розповіли серверу, де саме погляд нам все одно потрібно визначити шлях, за допомогою якого погляд повинен відображати. Почнемо з визначення базового шляху в APP/urls.py, і ми перейдемо до груп шляху пізніше. У APP/urls.py додайте рядок після операторів імпорту після початку імпорту подання, який ми тільки що створили.

from feed import views as feed_views
Тепер давайте визначимо схему перегляду. Шаблони перегляду мають три компоненти, компонент шляху, який розповідає серверу, де перегляд існує на сервері (шлях URL, який користувач вводить у панель навігації для введення веб -сторінки), компонент перегляду, де вказано перегляд, та a Дружнє ім’я для перегляду, тому легко отримати його шаблон під час роботи з шаблоном, особливо, щоб назва можна було змінити та оновити, якщо необхідно, щоб зробити місце для іншого виду або взяти на себе більш логічне ім'я. Має сенс робити речі таким чином і бути гнучким, оскільки ваша кодова база буде постійно мінливим середовищем, яке потребує гнучкості та імпровізації, щоб бути цінним та легким для роботи. Ось як виглядатиме ваш погляд, ви можете додати це до urlpatterns = [розділ програми/urls.py. Шаблон перегляду визначається трьома описаними вище компонентами, а також функцією, що називається шляхом. Ваші шаблони URL -адрес - це список, тому обов'язково завжди закінчуйте кожен предметз комою, бо це розділяє кожну. Кожен елемент також повинен надходити на новий рядок, ще раз із чотирма пробілами перед ним, як і додаток у Settings.py. Ми визначимо перший компонент перегляду з порожньою функцією рядка, щоб створити вигляд, який працює на кореневому каталозі веб -сервера. Ваші urls.py тепер повинні виглядати як

from feed import views as feed_views

urlpatterns = [
    path('', feed_views.hello, name='hello'),
]
Це основа для створення веб -сайту з Django, який є абсолютно статичним. Для того, щоб зробити більш динамічний веб -сайт, де ми можемо почати кешування інформації, як -от зображення, відео, аудіо та інше, нам потрібно буде використовувати моделі, які ми будемо вивчати далі. Поки що перевіримо наш код і запустимо сервер. Щоб перевірити код на помилки, запустіть:

python manage.py check
Якщо є якісь повідомлення про помилки, ви повинні ретельно переглянути зміни, які ви внесли у свій додаток, і побачити, чи є щось, що потрібно виправити, як сторонні або не вистачає місця, додатковий символ, незмінний рядок, будь -який друкарський, будь -який випадково видалений персонаж або щось інше. Читаючи повідомлення про помилку (якщо у вас є), ви повинні мати можливість переглянути шлях до створеного вами файлу або редагування разом із номером рядка, тому перегляньте цей файл і рядок і подивіться, чи можете ви виправити все, що там є . Якщо ви вирішили проблему, запустіть вищевказану команду. Коли ваше програмне забезпечення буде готове до запуску і працює, ви побачите вихід "Перевірка системи не визначила проблем". Тепер ви готові йти. Запустіть сервер із:

python manage.py runserver 0.0.0.0:8000
Тепер відкрийте веб -браузер і перейдіть до http: // localhost: 8000. Ви повинні побачити текст, повернутий у дужках та цитати функції httpresponse у вашому погляді. Це просто основний приклад, але якщо ви зробили це так далеко, ви розумієте основи того, як працюють Linux, Bash, Python та Django. Давайте заглиблюватися в деяке моделювання бази даних та вивчимо потужність класу Python у зберіганні інформації. Потім ми почнемо захоплювати HTML та CSS, перш ніж зробити наш сайт повністю представленим, гнучким та безпечним за допомогою JavaScript та машинного навчання. Заняття зберігаються в моделях.py вашого додатка. Використовуючи нано, редагувати додаток/моделі.py та додайте новий клас. Клас визначається з визначенням класу і передається суперкласом, від якого він успадковує, у цьому випадку моделі. Модель. Назва класу з'являється після визначення класу, і після використання визначення класу A: (Колон) використовується, перш ніж атрибути та визначення функцій, пов'язані з класом, позначаються нижче. Наш класПотрібен ідентифікатор, який ми можемо використовувати для отримання його та збереження унікальним, а також йому потрібне текстове поле для зберігання певної інформації. Пізніше ми можемо додати часову позначку, файли, булеві (правдиві або помилкові визначення, які можуть допомогти нашому коду прийняти рішення про те, що робити з моделлю, і може бути використаний для її сортування), екземпляр для прив’язки моделі до користувача, зареєстрованого на сервер та багато іншого. Давайте розпакуємо код

from django.db import models # Імпорт, який використовується для визначення нашого класу та його атрибутів

class Post(models.Model): # Визначення нашого класу самого класу
    id = models.AutoField(primary_key=True) # Ідентифікатор нашої моделі, автоматично створений ключ, який дозволить нам запитувати модель, зберегти її унікальною і є корисною, коли нам потрібно взаємодіяти з моделлю після її створення.
    text = models.TextField(default='') # Атрибут нашого класу, в даному випадку, якийсь текст, за замовчуванням порожній рядок.
Закрийте і збережіть файл, як і раніше, щоб закінчити. Існує багато інших полів та варіантів, які ми вивчимо, коли ми оновлюємо цей клас у міру розвитку нашої програми, але це основні потреби створення програми для розміщення певного тексту. Однак ця модель не буде працювати поодинці. Як описано раніше, нам знадобиться власний перегляд та спеціальний візерунок URL -адреси, щоб ця модель працювала, і нам також знадобиться форма разом із шаблоном. Давайте спочатку вивчимо форму. Щоб визначити форму, редагувати додаток/forms.py з нано та додайте наступні рядки. Нам знадобиться два імпорту, наш клас форм, а також модель, яку ми створили (Feed.models.post), визначення класу, подібне до моделі, та поле разом із підкласом під назвою META, який визначатиме модель, що взаємодіє форма з. Форма також може мати функцію ініціалізації, яка налаштовує її на основі інформації у запиті, моделі чи іншим чином, ми вивчимо це пізніше. Форми моделі настільки корисні, оскільки вони можуть створити модель або також редагувати модель,Тож ми будемо використовувати їх для обох. Давайте визначимо його у формах.py

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
Це займе хвилину, щоб виконати, але як тільки це станеться, це дозволить вам отримати доступ до моделі в переглядах, проміжному програмному забезпеченні чи де -небудь в програмному забезпеченні. Давайте продовжимо, оглядаючи, де ми можемо побачити нашу модель. Редагувати канал/views.py та додайте наступний код, як зазначалося. Вам не потрібно буде додавати нічого після знака #, що код - це коментарі, які використовуються для позначення інформації про код. Ми почнемо з імпорту нашої моделі в переглядах та додаванням до контексту, де ми можемо зробити її в шаблоні як список для дисплея. Далі ми додамо шаблон, де ми можемо зробити форму та модель за допомогою кнопки, щоб створити новий об'єкт на основі моделі та розмістити його на сервер. Це звучить складно, тому давайте просто зробимо крок за кроком. Перш ніж ми закінчимо вигляд, давайте створимо шаблон, який просто робить модель і переконайтеся, що ми можемо її побачити, створивши нову публікацію в оболонці. Ось як виглядати ця думка:

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 -відповіді, як і попередній приклад, завжди приймає запит як перший вхід , і повертає шаблон, визначений у функції. Шаблон буде документом HTML з невеликою мовою під назвою Jinja2, який надає Python інформацію в HTML. Щоб почати створювати шаблони, зробіть два каталоги в кормі.

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.py та додайте наступне до шаблонів URL -адрес

from django.urls import include # вгорі

urlpatterns = [
    # ... Попередній код тут
    path('feed/', include(('feed.urls'), namespace='feed')),
]
Тепер, коли ми запускаємо сервер за допомогою Python Manage.py Runserver, ми побачимо створену нами сторінку, оскільки у нас є модель, перегляд та шаблон, а також шаблон URL -адреси, а також елементи в базі даних. Далі, давайте реалізуємо форму, яку ми створили, і почнемо створювати власні публікації. Але перш ніж ми напишемо занадто багато коду, давайте зробимо резервну копію за допомогою сценарію, який ми писали раніше, резервне копіювання. Запустіть цей сценарій в оболонці, зачекайте кілька моментів, і весь код буде підкріплений нашому сховищі GIT.

backup
Реалізація форми порівняно проста. Ми імпортуємо нашу форму, додамо обробник запиту на публікацію до перегляду та збережемо публікацію в базі даних, перш ніж перенаправляти на той самий вигляд. Ми можемо використовувати функцію перенаправлення, яку ми вже імпортуємо, та іншу функцію під назвою Reverse, щоб отримати URL -адресу для шаблону перегляду. Ми запитаємо це за допомогою рядка "подача: подача", оскільки простір імен включеного шаблону подача, а вид також називається подачею.

from feed.forms import PostForm

def feed(request):
    posts = Post.objects.all() # Запитайте всі публікації в базі даних досі
    if request.method == 'POST': # Обробляйте запит на публікацію
        form = PostForm(request.POST) # Створіть екземпляр форми та збережіть до неї дані
        if form.is_valid(): # Валідувати форму
            form.save() # Збережіть новий об’єкт
        return redirect(reverse('feed:feed')) # Перенаправлення на ту саму URL -адресу з запитом GET
    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, вбудований, або в класах, прив'язаних до кожного об'єкта в документі. CSS справді приємний, тому що він розповідає все на сторінці, як це повинно виглядати,і може зробити це дуже добре. Є кілька бібліотек, які можуть це зробити, але мій особистий рух - Bootstrap. Bootstrap можна завантажити зі свого веб -сайту,getbootstrap.com/. Потрапивши туди, натисніть кнопку, щоб прочитати документи про встановлення та скопіюйте код із розділу VINCE CDN. Вам знадобиться цей код у верхній частині вашого документа 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, щоб зробити наш сайт більш функціональним у майбутньому. Тепер повернемося до оболонки баш і запустимо швидку команду. Пам'ятайте, якщо вам коли -небудь потрібно отримати доступ до віртуального середовища, введіть джерело venv/bin/активуйте. Це дозволить вам встановити пакети Python локально таким чином, щоб дозволити Джинго отримати доступ до них. Щоб надати наші форми, створені заняттями Django Bootstrap, ми будемо використовувати пакет 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. Модель користувача - це модель бази даних, як і наша публікація, яку можна зробити для входу користувача на веб -сайт. В майбутньому, перш ніж ми розгортаємо сайт в Інтернеті, ми будемоРозширюйте цю модель з іншими моделями, що пояснюються ним, і створіть додаткові заходи безпеки для входу, стійких до фішингу. Ми почнемо з використання деяких вбудованих у формах входу, які надає Джанго. По -перше, давайте створимо новий додаток, який ми будемо використовувати для візуалізації шаблонів та перегляду для основної сторінки входу. Ми також створимо інші програми для представлення постійних проблем входу, щоб забезпечити додаток, включаючи піндод, розпізнавання обличчя, польові зв'язки, зовнішні пристрої, багатофакторну автентифікацію та розпізнавання відбитків пальців. Ми вже говорили про створення програми. З нашого каталогу, всередині віртуального середовища, пропустіть

python manage.py startapp users
Тепер ми повинні мати каталог для нового додатка. Почнемо з створення подання в тому каталозі, який відповідає входу користувача. 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 користувачами/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']
Отже, у нас є інша форма, яка працює досить просто. Це форма реєстрації користувачів із іменем користувача, електронною поштою та паролем, а також полем підтвердження пароля. Зауважте, що ця форма не розширює звичайні форми. Одне поле визначається так само, і мета класу визначає модель, що форма відповідає решті інформації, яка буде записана у форму. Більшість цього вже існує в побудованому Django в UserCreationForm, тому ми будемо використовувати це як основу для класу (передані в дужках). Далі ми розглянемо перегляд, щоб зареєструвати користувача, тепер, коли у нас є форма та шаблон. Це моделформ, як і той, що в новому поданні публікації. Редагувати користувачів/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})
Це все, що нам потрібно, щоб зареєструватися користувачем, але ми повинні мати більше інформації. Ми хочемо знати час, коли користувач зареєстрував, який час вони останній на сайті, якась інформація про них, як -от біографія, часовий пояс тощо. Модель та атрибути для кожного користувача. Для цього ми оновимо моделі.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='')
Зверніть увагу на другий рядок, який був доданий до файлу. Це іноземний ключ, який приписуватиме кожну публікацію одному користувачеві за публікацію, тому ми можемо переконатися, що ми зберігаємо публікації на основі користувача за користувачем, і жодна публікація не може бути зроблена без приписування його користувачеві. Ми визначаємо цей іноземний ключ за допомогою класу, який він представляє, аргументом видалення, щоб забезпечити видалення публікацій за допомогою користувачів, нульові та порожні аргументи, щоб переконатися, що ми можемо видалити користувача, якщо це необхідно Створено та пов'язане ім'я, яке ми можемо використовувати для позначення об'єктів публікації, які створює користувач. Це пов'язане ім'я, на відміну від Post.author, автор публікації, дає нам користувача, який опублікував саму публікацію. Тепер ми можемо отримати публікації користувача, зробленого запуску user.posts.all () або author.posts.all (). Тепер давайте зробимо наші входи більш стійкими. Ми вже можемо зробити наш сайт набагато менш вразливим до фішингу, просто обмежуючи кількість разів, коли ми дозволимо вхід доСайт, це досить просто. Почнемо також зберігати деяку інформацію про кожного користувача раніше, коли ми продовжуємо розробляти нашу програму. Редагування користувачів/моделей.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. У нас є додатковий імпорт, Timezone, який дозволить нам встановити за замовчуванням на полях DateTime, а також у нас є персонаж Feild та TextField, як публікація. Використання всіх цих часових позначень допомагає нам захистити сайт та зрозуміти його використання, а текстові поля дозволяють нам надати інформацію про кожного користувача чи автора на веб -сайті. Onetoonefield повинен бути єдиним незначним увагою, воно поводиться точно так само, як і з лише одним на наступну модель. Таким чином, у користувача є лише один профіль, тоді як у них може бути багато публікацій. Тепер давайте вдосконалюємо наш логін та зареєструємось для обліку профілю. По -перше, редагувати користувачів/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()})
Це основна основа безпеки. Переконайтесь, що сайт не вразливий до того, що хтось просто пробує кожну можливу комбінацію паролів, або навіть декілька з них одночасно. Це не буде неприємно для звичайного користувача, який знає свій пароль і просто входить на кілька пристроїв, але це дозволить утримати численних фішингових роботів поза додатком. Зауважте, що ми додали оператор IF зі змінною, CAN_LOGIN, це має бути часом у минулому, і оновлювати його з кожним невдалим входом, використовуючи одне і те ж ім'я користувача. Таким чином, зловмисний користувач не зможе здогадатися про пароль ніде поблизу так швидко. Кількість секунд у dateTime.timedelta () також може бути оновлена, і веб -сайт буде більш стійким, але трохи менш корисним за допомогою більше секунд. Я рекомендую 15 для початку. Пам'ятайте, ми створили резервний сценарій, щоб врятувати нашу роботу, тож давайте продовжимо і резервні копії, що маємо до цього часу, щоб переконатися, що у нас все збережено. Запустіть команду:

sudo backup
Ще раз це врятує вашу роботу поки що. Я рекомендую запускати часті резервні копії, щоб зберегти свою роботу, і ви навіть можете автоматично запустити резервну роботу. Ви можете зробити це за допомогою Unix Unix під назвою Cron. Щоб активувати цю утиліту, запустіть наступну команду та введіть свій пароль:

sudo crontab -e
Якщо ви ще не вибрали варіант 1 для Nano, текстовий редактор, з яким ви вже повинні бути знайомі, і прокрутіть до нижньої частини файлу за допомогою клавіш зі стрілкою. Додайте наступний рядок:

0 * * * * sudo backup
Cron використовує формат хвилини, годину, день місяця, місяць, день тижня, де * або число являє собою, коли запускати команду. Використовуючи 0 для хвилини та * для решти параметрів, ми можемо запустити команду на першій хвилині кожної години на початку хвилини. Це дозволяє нам автоматично створити резервну копію коду. Усі завдання Крон, виконані з Sudo, запускаються як Root, тому нам не потрібно буде вводити пароль щогодини. Щоб полегшити резервну копію наш код без використання пароля, давайте відключимо пароль для нашої команди резервного копіювання. Ми зробимо це, виконуючи таку команду та ввівши пароль:

sudo visudo
Тепер давайте прокрутимося внизу файлу і додамо інший рядок:

ALL ALL=NOPASSWD: /bin/backup
Це дозволяє нам запускати команду "резервне копіювання" як будь -який користувач, без пароля. Формат для цього простий, просто призначте рядок з "All All = nopasswd:/bin/" і закінчити команду, наприклад,/bin/backup, який існує в/usr/bin/. Тепер почнемо працювати з електронною поштою. Електронна пошта дійсно важлива для веб -сайтів, оскільки це спосіб зберегти веб -сайт більш безпечним, перевірити, що користувачі є реальними людьми та навіть ринковими продуктами чи послугами для клієнтів. Багато людей, які часто відвідують Інтернет, перевіряють свою електронну пошту щодня, і отримують всілякі маркетингові електронні листи про продукти та послуги, які їх цікавлять. Є кілька варіантів, коли мова йде про ввімкнення електронної пошти на веб -сайті Django, і ви можете вибрати Незалежно від того, що найкраще працює для вас. По -перше, ви можете оплатити послугу електронної пошти, яка дозволить вам надсилати електронний лист із домену та вимагає мінімального коду. Існує багато служб, які пропонують це, такі як Google Workspace, SendinBlue, Mailgun тощо. В іншому випадку ви добре відбулисяВаша власна сервіс електронної пошти на вашому сервері з нуля. Я рекомендую цей варіант, навіть якщо він більше коду і може зажадати спеціального хостингу. Ви не зможете запустити поштовий сервер із домашнього комп'ютера, швидше за все, тому давайте продовжимо і вивчимо конфігурацію та код, щоб надсилати електронний лист, перш ніж ми запустимо сервер у хмарі та створимо власний поштовий сервер всередині. По -перше, редагувати налаштування.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) повинен бути встановлений на пароль, який ви генеруєте для сервера. Я завантажую пароль з конфігураційного файлу, щоб він не був від коду за допомогою наступної логіки, над цими рядками в Settings.py:

import os
import json
with open('/etc/config.json') as config_file:
    config = json.load(config_file)
Потім я налаштував файл JSON з Config in /etc/config.json, використовуючи Nano наступним чином. Редагувати файл:

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 -адреси для сайту, ідентифікатора користувача та маркера, які використовуються для перевірки електронної пошти користувача. Не забудьте визначити базову URL -адресу в налаштуваннях.py, перш ніж писати якийсь код Python, щоб зробити шаблон. Вперед і додайте наступні рядки до app/settings.py, на початку.

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

BASE_URL = PROTOCOL + '://' + DOMAIN
Врешті -решт, коли ваш сайт буде готовий до Інтернету і ви розгортаєте його, ви хочете визначити свій домен як доменне ім’я, яке ви купуєте для представлення сайту. Це ім'я, яке ви введете в NAVBAR, щоб отримати доступ до свого сайту. Поки що ви можете залишити домен порожнім або використовувати заповнювач. Ви також захочете змінити ім'я сайту на ім'я, яке ви хочете дати свій сайт, на вибір. Перш ніж надсилати електронну пошту, давайте створимо генератор маркерів, щоб ми могли мати маркер активації облікового запису, який ніколи не закінчується. Ми можемо це зробити, будуючи та імпортуючи маркер активації облікового запису, який виглядає як наступне. Відредагуйте файл:

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. Нарешті, ми перевіряємо, чи надісланий електронний лист, і якщо цього не було, ми позначаємо в профілі користувача, що їх електронна пошта не є дійсною. Давайте повернемося до моделей користувачів, щоб ми могли зробити це все. Нам потрібно визначити функцію для створення посилання на скасування підписки та визначити булеве поле, щоб позначити, що електронна пошта користувача не є дійсною. По -перше, додайте наступний імпорт до вершини користувачів/моделей.py

nano users/models.py

# ...
from django.core.signing import TimestampSigner, BadSignature, SignatureExpired
from django.urls import reverse
Далі, додамо функції до моделі користувача, щоб зробити маркер та перевірити маркер, який використовується для активації електронної пошти, а також поле, щоб зберегти, чи успішно користувач отримує свою пошту. У користувачів/моделей.

# ...
    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,})
Це досить просто, ми використовуємо TimestampSigner, який є основним інструментом криптографії, щоб створити маркер, який закінчується через певну кількість часу, а також ми використовуємо іншу функцію, щоб перевірити, чи вона дійсна. Ми використовуємо ці жетони двічі, один раз для перевірки електронної пошти та один раз для скасування підписки. Тепер, коли ми маємо це, останнє з роботи, яку нам потрібно буде зробити, - це погляди. У межах користувачів/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
Можливо, у вас вже є деякий з цих імпортів, але повторювати їх не завадить. Вам потрібно буде імпортувати функцію надсилання електронної пошти перевірки, а також 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()
# Sendwelcomeemail (запит, користувач)
        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})
Це багато коду. Давайте розберемо його. Перша функція, чиста і проста, скасовує користувача зі списку розсилки. Друга функція активує їх електронну пошту, і ви помітите, що я додав коментувану функцію, Sendwelcomeemail. Ви можете використовувати шаблон електронної пошти та визначення функції, щоб надіслати привітання електронної пошти, я просто ще цього не зробив. Остання функція, яку я кинув, є важливою, оскільки закінчується термін дії електронних листів активації. Тому нам потрібно буде деякий час надіслати електронну пошту з активацією. Ми можемо використовувати для цього основну форму та зателефонувати на функцію, щоб надіслати електронну пошту перевірки. Перш ніж ми це зробимо, давайте переконаємось, що він надсилається в першу чергу, додавши функцію виклику до перегляду реєстру. Додайте цей рядок безпосередньо перед перенаправленням у перегляді реєстру, DEF Register, у користувачів/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, тому що ми додаємо їх, коли додаємо посилання на скасування HTML. Вони важливі, але ми не хочемо їх визначати двічі. То що далі? Ми пройшли довгий шлях. Дійсно, ми повинні бути готові розгорнути сайт на сервер. Ми можемо додати декоратор @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 %}
 
Шаблон для самої електронної пошти простий, це основне HTML -файл, що відображає посилання на скидання пароля, у користувачів/шаблонах/користувачів/пароля_eset_email.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>
 
Нам також знадобляться ще два шаблони. Перший - це підтвердити, що електронний лист надіслав. Погляди на них вже в Джинго, тому нам просто потрібно звернутися до них у urls.py. Цей шаблон розташований на користувачах/шаблонах/користувачі/пароль_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'),
]
Чотири шаблони, це багато! Але тепер ми можемо бути впевнені, що зможемо скинути пароль користувача в будь -який час, коли нам потрібно, все з веб -браузера. Я розумію, що це багато коду. Якщо це здається трохи над головою, це нормально. Ви покращите, ваше розуміння покращиться, і ви станемо набагато компетентнішими з кодом дуже скоро. Якщо ви повністю загублені, я рекомендую повернутися до цього програмного забезпечення пізніше після роботи над самостійним кроком "Навчитися кодувати курс в Інтернеті. Зазвичай вони вільні для початку, і проведуть вас через усе, що вам потрібно, щоб досягти успіху, коли ви повернетесь до цього проекту. Якщо ви відчуваєте, що готові продовжувати, читайте далі, далі, ми висвітлимо розгортання вашого коду на віддалений сервер та налаштовуємо поштовий сервер, а також автоматизуючи розгортання за допомогою 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
Переконайтеся, що ваші користувачі/моделі.py виглядає так, крім коментарів (код у рядках з #). Розбиваючи це, це просто. У нас є кілька імпорту, часовий тілесний показник, який є криптографічною утилітою, яка може генерувати безпечний код і перевірити його, щоб переконатися, що він є дійсним, використовувався лише один раз, а не старше певної кількості секунд. Ми також використовуємо UUID, який є унікальним ідентифікатором, який ідентифікує нашого користувача у підписанні маркера та в URL -адресі, де маркер надсилається користувачеві. Ми використаємо цю основну криптографію для створення двофакторного виду аутентифікації. Перш ніж ми зробимо щось інше, запустимо міграцію, щоб наші моделі користувачів оновлювались. У каталозі з 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()})
Тож це досить просто, тепер у нас є спосіб перенаправити на подання аутентифікації двох факторів, коли ми його створюємо. У нас також є резерв, якщо користувач не додав номер телефону. Незабаром ми додамо базовий вигляд, щоб додати номер телефону та ввійти з текстовим повідомленням незабаром. По -перше, нам потрібен простий спосіб надіслати текстове повідомлення з нашого коду. Для цього ми можемо вибрати з ряду API, але найпростішим, на мою думку, є Twilio. Вони також пропонують хороші ціни для менших проектів, а також об'ємних знижок. Створіть обліковий запис на twilio.com, заповніть деякі деталі про свій проект, придбайте номер телефону та скопіюйте свої ключі API на свої settings.py. Потім додайте цей код у новий файл, користувачі/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 активна після інстанції
По -перше, нам знадобляться форми для наших двох факторних поглядів аутентифікації. Редагування користувачів/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 %}
 
Це досить само пояснюючи. Форма надсилає або код, або порожній код, і ви помітите в поданні, ми надсилаємо код, якщо отримаємо порожній код. Тоді у нас є дві кнопки подання, і таким чином ми можемо надіслати код будь -якою кнопкою. Далі ми додамо просту форму, щоб додати номер телефону.

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. Цей вигляд оновлює біографію, електронну пошту, ім’я користувача та номер телефону, а також дозволить нам дозволити багато факторів. По -перше, нам знадобиться ще дві форми в користувачах/формах.py

# ... суми
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 -адреси, які ми раніше вводили, додайте наступні три рядки
    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, це гарна ідея, щоб увімкнути дві факторні автентифікацію в обліковому записі. Ми зробимо це, перейти до нашої URL -адреси профілю,/користувачів/профіль/, а також встановити поле, щоб увімкнути аутентифікацію після введення нашого номера телефону, а потім подати форму.

python manage.py runserver localhost:8000
Відвідайте веб -сторінку, перейшовши до свого веб -браузера, я використовую Google Chrome у цьому прикладі та вводячи URL HTTPS: // LOCALHOST: 8000/ACCOUNTS/Профіль/Профіль/ Ви зможете увійти, якщо це необхідно, і ввімкнути аутентифікацію двох факторів. Цей проект потребує сервера для запуску, щоб він справді міг відправити пошту. Але спочатку нам потрібен спосіб побачити помилки. Ви помітите, що якщо ви запустите сервер у режимі налагодження, з settings.debug дорівнює справжньому, сервер автоматично показує помилки. Щоб показати помилки, не використовуючи режим налагодження, що небезпечно на виробничому сервері, ми повинні додати вигляд для нього. Найважливіші помилки, з якими ми повинні вміти впоратися: Помилка 500 - проблема з нашим кодом Помилка 404 - сторінка, яка не знайшла (зламана URL -адреса) Помилка 403 - дозвіл заперечується помилка Додамо новий додаток для обробки цих помилок, що називається помилками.

python manage.py startapp errors
Додайте це до settings.py, як ми це робили раніше, у налаштуванні встановлення_apps, і почніть з додавання посилань до деяких переглядів у додатку/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 у settings.py, з назвою нашого середнього програмного забезпечення.

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.')
Ми додаємо функцію, щоб отримати поточний виняток, використовуючи локальну різьбу, що допомагає нам простежити будь -які помилки в нашому коді. З точки зору шаблонів, нам потрібен лише один, оскільки ми динамічно визначаємо заголовок у погляді. Шаблон просто повинен зробити назву та "слід", наш слід про помилку від контексту.

nano errors/templates/errors/error.html
 
{% extends 'base.html' %}
{% block content %}
<h1>{{ pagetitle }}</h1>
<p>{{ trace }}</p>
{% endblock %}
 
Це наш найпростіший шаблон досі, але так легко побачити помилки в нашому проекті. Далі відключимо налагодження в налаштуваннях.

nano app/settings.py
Знайдіть цей рядок, де він встановлений на істину, і змініть його на фальшивий

DEBUG = False
Вперед і резервне копіювання програми зараз. Ми готові розгорнутись на віддалений сервер Linux і продовжуємо додавати функції звідти.

sudo backup
Перш ніж ми опублікуємо цей код на сервер, ми повинні врахувати, що з кодом можуть виникнути деякі проблеми. Залежно від справи, сайти, які приймають інформацію, розміщуються, матимуть проблеми з розміщенням спаму та труднощами усунення спаму. Це не повинно відбуватися негайно, але якщо це відбудеться, ми пізніше вивчимо, як автоматично поміркувати спам на сайті та зробити його жорсткішим для доступу до сайту, а також, як деактивувати облікові записи користувачів та перевірити особу користувача за допомогою Сканування їх посвідчення особи або біометричного сканування, як відбиток пальців або розпізнавання обличчя. Дивлячись на приклад багатофакторної автентифікації, який ми вивчали у виробництві, все може бути різним. Зверніть увагу, як ми обмежуємо входи, що обмежуємо тарифи, і термін дії жетонів. Якщо роботи отримують доступ до сайту, аутентифікація з двома факторами може бути складнішою, оскільки вони можуть вводити коди одночасно з користувачем. Щоб боротися з цим, давайте використаємо модель у моделях користувачів, заявляючи, як ми взаємодіємо з сайтом, коли миавтентифікація за допомогою багатофакторної автентифікації за номером телефону. Ми також додамо можливість для автентифікації електронною поштою. Почніть з редагування моделей користувачів за допомогою

nano users/models.py
Це те, як повинна виглядати модель, яку ми додаємо. Нам не потрібні будь -які методи, просто змінні для зберігання ідентифікатора, користувача, часової позначки, терміну придатності, довжини та спроб проти будь -якої багатофакторної автентифікації (такий код, як 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)
Як і в будь -яких змінах бази даних, нам потрібно здійснити міграцію та мігрувати базу даних у будь -який час, коли ми редагуємо файл моделей.py у Django. Пам'ятайте, що для цього ми спочатку використовуємо джерело (якщо воно вже не використовувалося з моменту відкритого терміналу), а потім Python керує.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
        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 # Увімкнути МЗС
            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): # Якщо запит - це запит на публікацію
        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) # Перевірте маркер Auth
            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('/'))
    # Надайте форму (для отримання запитів)
    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
Це спільно з шаблоном користувачів/користувачів.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'),
# ...
Тепер переконайтеся, що створити резервну копію сайту, щоб ви могли завантажити його на веб -сервер, над яким ми продовжимо працювати. З командного рядка,

sudo backup
Тепер наш сайт резервно копіюється. Тож тепер у нас є ще кілька корисних функцій. А як щодо великої картини тут? Цей код все ще не доступний з Інтернету, у нас ще немає поштового сервера, і нам потрібно розширити нашу програму, щоб включити комплексний процес перевірки, а також плавні макети, щоб допомогти нам вивчити сайт, а також безпечні протоколи для автентифікації привілейованих користувачів . Ми дістанемося до всього цього. Найголовніше на даний момент буде просто отримати цей код в Інтернеті, що ми можемо зробити лише за допомогою декількох рядків BASH на сервері Ubuntu. Вам потрібно буде взяти напрокат сервер для цього, якщо у вас є сервер вдома та підписка на бізнес, яка дозволяє відкривати порти. Я особисто запускаю свій веб -сайт на HP Z440, який встановлюється в моїй квартирі, але зазвичай це набагато дешевше для основних потреб в оренді віртуального приватного сервера (VPS). Майте на увазі, що код, який ми зараз працюємоГотові використовувати те, що ми маємо для створення продукту. Переконайтеся, що будьте обережні, що ви робите з Інтернетом, переконайтеся, що якщо ви публічно розгортаєте цей веб -сайт на Інтернеті на сервері Linux, у вас є план блокувати небажані взаємодії з вашим веб -сайтом. Спочатку це, ймовірно, не буде проблемою, але ми розглянемо різноманітні рішення для боротьби з цим, включаючи машинне навчання, штучний інтелект та комп'ютерне бачення. Коли це стає проблемою, погляньте далі в цьому тексті для рішення. Що стосується оренди VPS, то можна багато місць, куди можна поїхати. Google Cloud має сервери VPS, Ionos, Kamatera, Amazon AWS та інші постачальники пропонують рішення хмарних серверів, які відповідатимуть нашим потребам. Вам потрібно буде натиснути їх форми та вибрати план, щоб розпочати роботу. Ви можете перейти з базовим планом з будь -яким постачальником, але переконайтеся, що постачальник дозволяє відкрити порти поштового сервера для надсилання електронної пошти (це повинен бути порт 587 та порт 25), деякі постачальники блокують ці порти. Поки що у мене бувДосвід EST з Ionos та Kamatera, вони обидва дозволять мені надсилати необмежену електронну пошту, і їх ціноутворення досить дешево. Ви підключитесь до свого нового сервера за протоколом під назвою 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
Створіть VPS, що працює на Ubuntu, проте ви плануєте це зробити. Після створення VPS, натиснувши форми на веб -сайті провайдерів (kamatera.com, ionos.com або подібне), ви хочете увійти. Для цього використовуйте команду SSH зі своєю IP -адресою (адреса Це виглядає як xx.xx.xx.xx). Вам також потрібно бути чутливим до імені користувача за замовчуванням на сервері, який ми створили, наприклад, Ubuntu.

ssh ubuntu@XX.XX.XX.XX
Можливо, вас попросять пароль, якщо вас попросять пароль, введіть його. Ми не будемо використовувати ім'я користувача за замовчуванням, тому почнемо з створення нового користувача та додавання ключа SSH до свого облікового запису. Почнемо з додавання нового файлу SSHD_CONFIG, який повідомляє серверу, як використовувати SSH.

nano sshd_config

# Це файл конфігурації SSHD Server.  Бачити
# sshd_config (5) для отримання додаткової інформації.

# Цей SSHD був складений з шляхом =/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/ігри

# Стратегія, що використовується для параметрів у 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 за замовчуванням

# Реєстрація
# Syslogfacistility auth
# Інформація про реєстрацію

# Автентифікація:

# Logringracetime 2m
# Deversootlogin забороняє
# СТРИКТМОДИ ТАК
# Maxauthtries 6
# Максесії 10

PubkeyAuthentication yes

# Очікуйте .ssh/avollized_keys2 не враховується за замовчуванням у майбутньому.
AuthorizedKeysFile	.ssh/authorized_keys .ssh/authorized_keys2

# Avollizzyprincipalsfile None

# AllosizedKeyscommand None
# AlloizedKeysCommandUser ніхто

# Для цього вам також знадобляться клавіші хоста в/etc/ssh/ssh_ invellow_hosts
# HostBasedAuthentication NO
# Змініть на так, якщо ви не довіряєте ~/.ssh/know_hosts для
# HostBasedAuthentication
# Ігнорезер відомого
# Не читайте файли користувача ~/.rhosts та ~/.shosts
# Невігласи так

# Щоб відключити тунельні прозорі текстові паролі, змініть тут ні!
PasswordAuthentication no
# Directemptypasswords

# Змініть на Так, щоб увімкнути паролі відповіді на виклик (
# Деякі модулі PAM та нитки)
KbdInteractiveAuthentication no

# Варіанти Кербероса
# Kerberosauthentication №
# Kerberosorlocalpasswd так
# Kerberosticketcleanup так
# Kerberoscotted Rod No

# Параметри GSSAPI
# GSSapiauthentication NO
# Gssapicleanupcredentials так
# Gssapistrictacceptorcheck так
# Gssapikeyexchange

# Встановіть це на "так", щоб увімкнути автентифікацію PAM, обробку облікових записів,
# та обробка сеансу. Якщо це увімкнено, аутентифікація PAM буде
# бути дозволеним через KbDinterActiveAuthentication і
# Пароль  Залежно від конфігурації PAM,
# Аутентифікація PAM через KBDinterActiveAuthentication може обходити
# Налаштування "DeallootLogin без Password".
# Якщо ви просто хочете, щоб перевіри облікового запису та сеанси проходили без
# Аутентифікація PAM, а потім ввімкніть це, але встановіть пароль
# і KbDinterActiveAuthentication до "Ні".
UsePAM yes

# Дозволити зафіксовано так
# Allowtcpforwarding так
# Шлюзи ні
X11Forwarding yes
# X11displayOffset 10
# X11uselocalhost так
# Дозвіл Так
PrintMotd no
# Printlastlog так
# Tcpkeepalive так
# Дозвіл
# Стиснення затримки
# Клієнтський інтервал 0
# ClientAliveCountMax 3
# Використовуються в
# Pidfile /hrun/sshd.pid
# Maxstartups 10: 30: 100
# Pemittunl ні
# Chrootdirectory none
# Додаток до версії Немає

# Немає шляху банера за замовчуванням
Banner /etc/banner

# Дозволити клієнту передавати локальні змінні змінні
AcceptEnv LANG LC_*

# Переоцінка за замовчуванням відсутності підсистем
Subsystem	sftp	/usr/lib/openssh/sftp-server

# Приклад переважних налаштувань на основі користувача
# Відповідати користувачеві anoncvs
# X11Forwarding NO
# Дозволити
# Дозволити
# Сервер CVS Forcommand
PermitRootLogin no
Пам'ятайте, ctrl+x і y, щоб зберегти файл. Далі напишемо основний сценарій, який називається ініціалізацією (все в домашньому каталозі за замовчуванням нашого користувача).

nano initialize
Додайте ці рядки до файлу, замінюючиЗа допомогою ключа SSH ви знайшли за допомогою CAT. (.ssh/id_rsa.pub)

# ! / Бін / Баш
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, генеруючи клавіші SSH для Root, додавши команду користувача (ви можете вибрати ім'я, яке вам подобається, використовуйте команду AddUser з їх іменем та вимкненим паролем для пароля Тепер). Ми також додаємо команду до групи 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, EDIT/USR/BIN/ASCRIPT

sudo nano /usr/bin/ascript
Переконайтеся, що там використовуйте sudo, щоб у вас були дозволи для редагування файлу. У файлі додайте ці рядки:

# ! / Бін / Баш
if [ ! -f /usr/bin/$1 ]; then
    sudo touch /usr/bin/$1
    echo "# !
    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 долар. Спочатку він перевіряє, чи існує файл чи іншим чином його створює, додає перший рядок, щоб оголосити сценарій, є BASH, змінює його дозволи, редагує його та додає його назву до /etc /Ascripts, що дозволяє нам зберігати імена сценаріїв, які ми створюють. Якщо файл вже існує, просто змініть дозволи та редагувати його. Збережіть файл, а далі ми змінимо це дозволи. Поки ми використовуємо цей сценарій, нам не доведеться це робити знову.

sudo chmod a+x /usr/bin/ascript
Ідеально. Тепер давайте створимо сценарій під назвою Setup. По -перше, не переповнити вас, а погляньте на те, як виглядає мій сценарій налаштування. Ми розглянемо, як повинен виглядати цей сценарій у вашому проекті, вам не знадобиться все в моєму сценарії для початку.

# ! / Бін / Баш
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
# Нано -конфігурація
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
# Увімкнути Clamav Antivirus
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
# Налаштування PostFix
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
# Налаштування Virtuealenv
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 privke.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: 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
# Перезавантажте демон і перезапустіть Apache, Postfix та 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
# ІНТЕРИНАЦІЙНИЙ ДВИГАТЕЛЬ
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 Necounts, налаштовує Postfix, налаштовує PostGresQL (сервер бази даних) та завантажує базу даних, налаштовує UFW (нескладний бемданез), Вимкнено IPTABLES, завантажує антивірус, робить каталоги, залежності клонів, встановлює сертифікати та налаштовує сервер, встановлює конфігурацію, запускає та дозволяє розподіляти, замінює, встановлює дозволи та друкує IP -адресу IPv6 та клавішу Opendkim. Досить просто, але це виглядає як багато коду. Нам не знадобиться багато цього, тому що у нас немає залежностей, ми не використовуємо селеру, селекцію чи дафну, але ми встановимо деякі з них, щоб розпочати роботу. Зауважте, що цей код має домен, оголошений кілька разів. Нам також потрібно буде придбати доменне ім’я (що є невеликою щорічною плату). Я рекомендую Squarespace для придбання домену, їх макет -Інтуїтивно зрозумілий та простий у використанні. Ви можете придбати будь -який домен на ваш вибір, але я використовую домен femmebabe.com у цьому прикладі. Після того, як ви купили домен, перейдіть на панель конфігурації DNS Squarespace і додайте запис, що вказує на свій домен на сервер за IP -адресою. Це повинно виглядати так: @ Xx.xx.xx.xx З оператором @ в якості хоста, тобто всі субдомени під цим доменом та кореневим доменом перенаправляться на сервер. Є більше записів, які можна оголосити, але ми можемо перейти до них, як тільки ми будемо готові надіслати пошту. Майте на увазі, може пройти кілька днів, перш ніж ви зможете успішно відправити пошту з сервера. Записи DNS, які ми встановлюємо, потребує часу для поширення. У будь -якому випадку, єдиний запис, який нам потрібно почати, - це запис. Тож тепер ми можемо заповнити сценарій нижче відповідно до нашого проекту та запустити його. Почнемо з меншого сценарію налаштування, щоб просто встановити те, що нам потрібно для основного прогресу. Ми ще не будемо використовувати стільки залежностей або postgresql, ми простоВгору базовий HTTP -сервер і турбуйтеся про його засвідчення, коли це буде зроблено. Пам'ятайте, щоб отримати сертифікат HTTPS та надійно запустити сервер, нам потрібно буде придбати домен разом з орендою сервера. Наразі замініть "Команда" у цьому файлі на ім'я свого користувача "DIR" на каталог вашого проекту та надайте електронну пошту та домен у тегах <>. Крім того, перед тим, як запустити цей код, нам потрібно змінити налаштування на брандмауер, який підтримує хостинг -провайдер, якщо такі є. Зазвичай це на вкладці "Мережі" вашого хостингового постачальника, або якщо ви самостійно хостинг, його в розділі "Переадресація порту" вашого маршрутизатора. Ви також захочете налаштувати статичний IP через свій маршрутизатор із адресою вашої серверної машини, якщо ви використовуєте самостійне хостинг. Вам потрібно буде відкрити наступні порти для доступу до читання/запису. 22 (SSH) 25 (пошта) 587 (пошта) 110 (поштовий клієнт) 80 (HTTP) 443

# ! / Бін / Баш
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
# Нано -конфігурація
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
# Увімкнути Clamav Antivirus
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
# Налаштування Virtuealenv
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: 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
# Перезавантажте демон і перезапустіть Apache, Postfix та 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 # Вставте сюди свій домен, після пінг
Якщо все виглядає добре, і сервер надсилає відповіді, ми готові запустити сценарій та встановити пакети, а також запустити, увімкнути та засвідчити наш сервер Apache. Це не всі налаштування, необхідні для налаштування Postfix, ми розглянемо цю установку більше пізніше. Наразі запустіть цей код налаштування, і для встановлення та сертифікації сервера слід зайняти кілька хвилин. Ще раз обов’язково замініть ім’я, електронну пошту та доменне ім’я в сценарії відповідно до імені, яке ви придбали. Тепер, коли сервер надається, ви можете перейти до URL -адреси в будь -якому веб -браузері та перевірити, чи переконатися, що сервер працює HTTPS. Якщо це не так, спробуйте трохи чекати, коли записи DNS наздогнали, а потім запустіть наступну команду, щоб повторно повторно сертифікувати Certrbot:

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
Далі ми можемо включити сайт за замовчуванням та перезавантажити Apache2, також використовуючи Bash. Не забудьте замінити Femmebabe на ім'я файлу, який ви оголосили під час редагування в/etc/apache2/сайти, доступні/.

sudo a2ensite femmebabe-le-ssl
sudo systemctl reload apache2
Поверніться до свого домену в Навбарі. Ви повинні побачити сайт, який ви налаштували у своєму веб -браузері. Вітаємо! Якщо ви цього не бачите, можливо, вам доведеться внести деякі зміни. Ретельно перегляньте налаштування у вашому проекті, конфігурація Apache та переконайтеся, що у вас немає помилок, і запустіть наступні команди, щоб перевірити проект на наявність помилок.

cd projectname
source venv/bin/activate
python manage.py check
Якщо у вас є помилки у вашому проекті Python, простежте їх туди, де вони знаходяться, і виправте їх. Можливо, ви не зможете побачити всі ваші помилки залежно від того, де вони знаходяться, тому, якщо у вас є помилка, яка просто каже, що "населення не є повторним", відредагуйте наступний файл у віртуальному середовищі, registry.py, викрити помилка.

nano venv/lib/python3.12/site-packages/django/apps/registry.py
Перейдіть до рядка 83, де піднімається ця помилка часу виконання (підніміть Runtimeerror ("Poculate () не повторюється")) і додайте коментар до цього рядка, а потім додавання, з тим самим відступом, self.app_configs = {}. Це виглядає так:

            if self.loading:
                # Запобігти повторним дзвінкам, щоб уникнути запуску AppConfig.Ready ()
                # методи двічі.
# Підвищити RunTimeerror ("Poculate () - це не повторно")
                self.app_configs = {}
            self.loading = True
Потім ви можете перевірити проект ще раз і викрити помилку.

python manage.py check
Потім ви можете побачити помилку і виправити її. Коли у вас його виправлено, і код компілює без помилок, обов’язково змініть назад файл, щоб він виглядав так:

            if self.loading:
                # Запобігти повторним дзвінкам, щоб уникнути запуску AppConfig.Ready ()
                # методи двічі.
                raise RuntimeError("populate() isn't reentrant")
# self.app_configs = {}
            self.loading = True
За умови, що сервер є в Інтернеті, коли ми вносимо будь -які подальші зміни до нього, нам потрібно використовувати наступну команду для перезавантаження сервера:

sudo systemctl reload apache2
Дивовижно! А як щодо надсилання пошти? Щоб почати надсилати електронну пошту, спочатку нам потрібно буде оновити конфігурацію домену. Це має бути на вашій панелі DNS у Squarespace, або будь -якому реєстратору доменних імен. Нам також потрібно буде встановити та додати конфігурацію та запустити кілька команд. Спочатку давайте отримаємо адресу IPv6 сервера. Потім ми відкриємо ваші DNS та додамо записи. Щоб отримати адресу IPv6 сервера, використовуйте цю команду:

ip -6 addr
Тепер ми можемо додати наступні записи до налаштувань DNS. Мої записи виглядають так. Однак для своїх записів слід замінити IP -адресу на ваш IP (не 75.147.182.214, це моє). Також додайте свій домен замість femmebabe.com, а також вашу адресу IPv6, знайдену з попередньою командою (ви не можете використовувати мою, Fe80 :: 725A: FFF: Fe49: 3E02). Наразі не турбуйтеся про доменей, це створюється, коли ми налаштовуємо Postfix, поштовий сервер, з Opendkim, та надрукуємо ключ. Ми налаштуємо це останнє. @ 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 ~ всі за замовчуванням._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, на доменне ім'я, яке ви використовуєте. Давайте подивимось на всі конфігураційні файли по черзі та встановимо їх у каталозі під назвою Config в нашому проекті, щоб встановити в ОС.

nano config/etc_postfix_main.cf
Додайте цей текст у файл

# Див. /Usr/share/postfix/main.cf.dist для коментування, більш повної версії


# Debian Конкретний: уточнення імені файлу спричинить перше
# рядок цього файлу, який буде використовуватися як ім'я.  Дебіан за замовчуванням
# є /etc /mailname.
# myorigin = /etc /mailname

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

# Додавання. Домен - це робота Муа.
append_dot_mydomain = no

# Послідовність наступного рядка для створення попереджень про "затримку пошти"
# DALDE_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_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.  Детальніше про формат
# файлу див.
# Он-лінія: http://www.postfix.org/master.5.html).
# 
# Не забудьте виконати "Postfix Reload" після редагування цього файлу.
# 
# ===================================================== ========================
# Тип сервісу приватне uncriv chroot wakeup maxproc command + args
# (так) (так) (ні) (ніколи) (100)
# ===================================================== ========================
smtp      inet  n       -       y       -       -       smtpd
# smtp inet n - y - 1 Постекр
# SMTPD PASS - - Y - - SMTPD
# Dnsblog unix - - y - 0 dnsblog
# tlsproxy unix - - y - 0 tlsproxy
# Виберіть один: Увімкніть подання лише для клієнтів, що займаються петлями, або для будь -якого клієнта.
# 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/подання
# -o smtpd_tls_security_level = шифрування
# -O smtpd_sasl_auth_enable = так
# -o smtpd_tls_auth_only = так
# -o smtpd_reject_unlisted_recipient = ні
# -O smtpd_client_restrictions = $ mua_client_restrictions
# -O smtpd_helo_restrictions = $ mua_helo_restrictions
# -O smtpd_sender_restrictions = $ mua_sender_restrictions
# -o smtpd_recipient_trival =
# -o smtpd_relay_restrictions = DEVIRE_SASL_AUTHENTICT, відхилити
# -O milter_macro_daemon_name =
# Виберіть один: Увімкніть SMTPS лише для клієнтів, що займаються петлями, або для будь -якого клієнта.
# 127.0.0.1:Smtps inet n - y - - smtpd
# Smtps inet n - y - - smtpd
# -O syslog_name = postfix/smtps
# -o smtpd_tls_wrappermode = так
# -O smtpd_sasl_auth_enable = так
# -o smtpd_reject_unlisted_recipient = ні
# -O smtpd_client_restrictions = $ mua_client_restrictions
# -O smtpd_helo_restrictions = $ mua_helo_restrictions
# -O smtpd_sender_restrictions = $ mua_sender_restrictions
# -o smtpd_recipient_trival =
# -o smtpd_relay_restrictions = DEVIRE_SASL_AUTHENTICT, відхилити
# -O milter_macro_daemon_name =
# 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. Обов’язково вивчіть посібник
# Сторінки програмного забезпечення, що не є Postfix, щоб дізнатися, які варіанти він хоче.
# 
# Багато з наступних служб використовують доставку Postfix (8)
# агент.  Див. Сторінку PIPE (8) Жіноча інформація про $ {одержувач}
# та інші параметри конверта повідомлення.
# ===================================================== ===================
# 
# maildrop. Докладніше див.
# Також вкажіть у main.cf: maildrop_destination_recipient_limit = 1
# 
maildrop  unix  -       n       n       -       -       pipe
  flags=DRXhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
# 
# ===================================================== ===================
# 
# Останні версії Cyrus можуть використовувати існуючий запис Master.cf "LMTP".
# 
# Вкажіть у cyrus.conf:
# lmtp cmd = "lmtpd -a" listen = "localhost: lmtp" proto = tcp4
# 
# Вкажіть у main.cf одне або кілька з наступного:
# mailbox_transport = lmtp: inet: localhost
# Virtual_transport = lmtp: inet: localhost
# 
# ===================================================== ===================
# 
# Cyrus 2.1.5 (amos gouaux)
# Також вкажіть у main.cf: cyrus_destination_recipient_limit = 1
# 
# Cyrus unix - n n - - труба
# flags = drx user = cyrus arg =/cyrus/bin/deliver -e -r $ {sender} -m $ {extension} $ {user}
# 
# ===================================================== ===================
# Старий приклад доставки через Cyrus.
# 
# Старий -corus unix - n n - - труба
# flags = r user = cyrus argv =/cyrus/bin/doell -e -m $ {extension} $ {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 Service. Будь ласка, використовуйте відповідні параметри конфігурації в
# /etc/opendkim.conf.
# 
# Раніше можна було б відредагувати налаштування за замовчуванням тут, а потім виконати
# /lib/opendkim/opendkim.service.generate для генерації файлів systemd
# /etc/systemd/system/opendkim.service.d/override.conf та
# /etc/tmpfiles.d/opendkim.conf. Хоча це все ще можливо, це зараз
# Рекомендується регулювати налаштування безпосередньо в /etc/opendkim.conf.
# 
# Deemon_opts = ""
# Змініть на/var/spool/postfix/run/opendkim, щоб використовувати розетку Unix за допомогою
# Postfix в chroot:
# Rundir =/був/котуш/postfix/run/opendkim
RUNDIR=/run/opendkim
# 
# Нерозбірливий для визначення альтернативної розетки
# Зауважте, що налаштування це замінить будь -яке значення розетки на opendkim.conf
# за замовчуванням:
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
# Слухайте на всіх інтерфейсах на порту 54321:
# Розетка = inet: 54321
# Слухайте на Loopback на порту 12345:
# Розетка = 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 = 256 м

# Користувач для входу в систему використовується внутрішньо в процесах входу. Це найбільш ненадійне
# користувач у системі 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
  }

  # Створіть слухача inet лише в тому випадку, якщо ви не можете використовувати вищевказану розетку Unix
  # inet_lister lmtp {
    # Уникайте зробити LMTP видимим для всього Інтернету
    # Адреса =
    # порт =
  # }
}

service imap {
  # Більшість пам'яті переходить у файли mmap (). Можливо, вам доведеться збільшити це
  # Обмежте, якщо у вас величезні поштові скриньки.
  # vsz_limit = $ 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 процес тощо.
  # Повні дозволи цій розетці можуть отримати список усіх імен користувачів і
  # Отримайте результати пошуку кожного користувача.
  # 
  # Режим 0666 за замовчуванням дозволяє будь -кому підключитися до розетки, але
  # Пошуки userdb досягне успіху лише в тому випадку, якщо userdb поверне поле "UID", яке
  # відповідає UID процесу абонента. Також, якщо UID або GID Caller відповідає
  # uid або gid socket. Пошук досягає успіху. Все інше викликає невдачу.
  # 
  # Щоб надати абоненту повну дозволи шукати всіх користувачів, встановіть режим
  # Ще щось, ніж 0666, і Dovecot дозволяє ядру застосовувати
  # Дозволи (наприклад, 0777 дозволяє всім повними дозволами).
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }
}

service auth-worker {
  # Процес робітника Auth за замовчуванням виконується як корінь, щоб він міг отримати доступ
  # /etc/тінь. Якщо це не потрібно, користувача слід змінити на
  # $ default_interal_user.
  # користувач = root
}

service dict {
  # Якщо використовується DICT проксі, поштові процеси повинні мати доступ до його розетки.
  # Наприклад: режим = 0660, група = vmail та глобальна 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 = "# char і проміжок пробілу "

# Більшість (але не всіх) налаштувань можуть бути перекриті різними протоколами та/або
# Джерело/призначення IPS, розміщуючи налаштування всередині розділів, наприклад:
# Протокол IMAP {}, локальний 127.0.0.1 {}, віддалений 10.0.0.0/8 {}

# Значення за замовчуванням відображаються для кожного налаштування, це не потрібно роз'єднати
# ті. Це винятки з цього: немає розділів (наприклад, простір імен {})
# Або налаштування плагіна додаються за замовчуванням, вони вказані лише як приклади.
# Шляхи також є лише прикладами, коли реальні за замовчуванням базуються на налаштуваннях
# варіанти. Перераховані тут шляхи призначені для налаштування --prefix =/usr
# --sysconfdir =/etc-localstatedir =/var

# Увімкнути встановлені протоколи
!include_try /usr/share/dovecot/protocols.d/*.protocol

# Кома -розділений список IPS або хостів, де слухати для з'єднань.
# "*" слухає у всіх інтерфейсах IPv4 ",:" прослуховує всі інтерфейси IPv6.
# Якщо ви хочете вказати порти, що не є дефоутом, або щось більш складне,
# редагувати conf.d/master.conf.
# Слухати = *, ::

# Базовий каталог, де зберігати дані про виконання.
# base_dir =/var/run/dovecot/

# Ім'я цього екземпляра. У налаштуванні багатоповерхової установки та інших команд
# Можна використовувати -I <SIDANCE_NAME>, щоб вибрати, який екземпляр використовується (альтернатива
# до -c <config_path>). Назва екземпляра також додається до процесів DoveCot
# У вихідному PS.
# instance_name = dovecot

# Вітальне повідомлення для клієнтів.
# login_greeting = dovecot готовий.

# Простір розділений список надійних мережевих діапазонів. З'єднання з них
# IPS дозволяється перекрити свої 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_proctitle = ні

# Якщо всі процеси будуть вбиті, коли головний процес DOVECOT закривається.
# Встановлення цього "ні" означає, що Dovecot може бути модернізований
# Примушення існуючих клієнтських з'єднань закриватися (хоча це також може бути
# Проблема, якщо оновлення, наприклад, через виправлення безпеки).
# Shutdown_clients = так

# Якщо ненуль, запустіть команди пошти за допомогою багатьох підключень до сервера Doveadm,
# Замість того, щоб запускати їх безпосередньо в одному процесі.
# doveadm_worker_count = 0
# Unix Socket або Host: Порт, що використовується для підключення до сервера Doveadm
# doveadm_socket_path = doveadm-сервер

# Простір відокремлений перелік змінних навколишнього середовища, які зберігаються на Dovecot
# запуск і передав усім його дитячим процесам. Ви також можете дати
# КЛЮЧ = Пари значення, щоб завжди встановлювати конкретні налаштування.
# Import_environment = tz

## 
## Налаштування словника сервера
## 

# Словник може бути використаний для зберігання ключів = списки значення. Це використовується декількома
# плагіни. До словника можна отримати або безпосередньо, або хоча
# Словник Словника. Наступні назви словника карт DICT до URIS
# Коли використовується сервер. Потім можна посилатися на використання URI у форматі
# "Проксі :: <Ім'я>".

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

# Більшість фактичної конфігурації включається нижче. Імена файлів є
# вперше відсортовано за їх вартості ASCII і проаналізовано в такому порядку. 00-префікси
# Імена файлів призначені для того, щоб полегшити розуміння замовлення.
!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

nano config/etc_opendkim.conf
І додайте ці рядки:

# Це основна конфігурація для підписання та перевірки. Це може бути легко
# адаптований відповідно до основної установки. Див. OpendKim.conf (5) та
# /usr/share/doc/opendkim/examples/opendkim.conf.sample
# Документація доступних параметрів конфігурації.

Syslog			yes
SyslogSuccess		yes
# Logwhy ні

# Загальні параметри підписання та перевірки. У Debian, "від" заголовка є
# винищені, оскільки це часто ключ ідентичності, який використовується в системах репутації
# і, таким чином, дещо чутливий до безпеки.
Canonicalization	relaxed/simple
Mode			s
SubDomains		no
OversignHeaders		From

# Підписання домену, селектора та ключа (потрібно). Наприклад, виконайте підписання
# для домену "example.com" з селектором "2020" (2020._domainkey.example.com),
# Використання приватного ключа, що зберігається в /etc/dkimkeys/example.private. Більш детально
# Параметри налаштування можна знайти в /usr/share/doc/opendkim/readme.opendkim.
# Домен Приклад.com
# Селектор 2020
# Keyfile /etc/dkimkeys/example.private

# У Debian Opendkim працює як користувач "opendkim". UMASK 007 потрібен, коли
# Використання локальної розетки з MTA, які отримують доступ до розетки як непересіле
# Користувач (наприклад, Postfix). Можливо, вам доведеться додати користувача "postfix" до групи
# "Opendkim" у цьому випадку.
UserID			opendkim
UMask			007

# Розетка для з'єднання MTA (необхідна). Якщо MTA знаходиться всередині в'язниці з чуватом,
# Потрібно забезпечити, щоб розетка доступна. У Debian, Postfix працює
# Chroot In/var/Spool/Postfix, тому повинен бути розетка Unix
# налаштовано, як показано на останньому рядку нижче.
# Локальна розетка: /run/opendkim/opendkim.sock
# Розетка inet: 8891@localhost
# Розетка inet: 8891
Socket			local:/var/spool/postfix/opendkim/opendkim.sock

PidFile			/run/opendkim/opendkim.pid

# Хости, для яких можна підписати, а не перевірити, за замовчуванням - 127.0.0.1. Див.
# Розділ операції Opendkim (8) для отримання додаткової інформації.
# Internalhosts 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12

# Якор довіри дозволяє DNSSEC. У Debian надається файл довіри
# за пакетом 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 Service. Будь ласка, використовуйте відповідні параметри конфігурації в
# /etc/opendkim.conf.
# 
# Раніше можна було б відредагувати налаштування за замовчуванням тут, а потім виконати
# /lib/opendkim/opendkim.service.generate для генерації файлів systemd
# /etc/systemd/system/opendkim.service.d/override.conf та
# /etc/tmpfiles.d/opendkim.conf. Хоча це все ще можливо, це зараз
# Рекомендується регулювати налаштування безпосередньо в /etc/opendkim.conf.
# 
# Deemon_opts = ""
# Змініть на/var/spool/postfix/run/opendkim, щоб використовувати розетку Unix за допомогою
# Postfix в chroot:
# Rundir =/був/котуш/postfix/run/opendkim
RUNDIR=/run/opendkim
# 
# Нерозбірливий для визначення альтернативної розетки
# Зауважте, що налаштування це замінить будь -яке значення розетки на opendkim.conf
# за замовчуванням:
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
# Слухайте на всіх інтерфейсах на порту 54321:
# Розетка = inet: 54321
# Слухайте на Loopback на порту 12345:
# Розетка = 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.

# ! / Бін / Баш
# Налаштування PostFix
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
Після того, як цей сценарій запустився, скопіюйте останній рядок, який він друкує та вставте його у свою конфігурацію DNS як значення для Sendonly._domainkey. Це ключ opendkim, який використовується для ідентифікації вашого домену під час надсилання безпечної пошти. Дивовижно! Протягом декількох днів ви зможете надсилати пошту з сервера за умови, що все налаштовано правильно. Якщо ви просто налаштували DNS для свого поштового сервера, для оновлення записів потрібно менше 72 годин. Зазвичай це набагато швидше. Ви можете перевірити, чи працює ваш сервер за допомогою цієї команди, постачає вашу електронну пошту:

echo “test” | mail -s “Test Email” youremail@gmail.com
Якщо все, здається, працює правильно, ви повинні мати можливість надсилати електронну пошту з вашим сервером. Якщо це не працює, спробуйте переглянути журнали, щоб побачити, якою може бути помилка.

tail –lines 150 /var/log/mail.log
Це запропонує багатослівну інформацію про пошту, яка надсилається сервером та чи працює вона належним чином. Ви повинні мати можливість побачити електронну пошту і у папці "Вхідні", якщо його немає, перевірте свою папку спаму. Вам також потрібно буде налаштувати свої налаштування у ваших settings.py, щоб ваш сервер електронної пошти могла поговорити з вашим додатком 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
Тепер спробуйте надіслати електронну пошту HTML з веб -сервера, що надає один із командного рядка працює. Запитайте ваш екземпляр користувача в Shell та надішліть електронну пошту HTML цьому користувачеві через Django. Змініть моє ім’я в коді, Шарлотта, на своє ім’я користувача.

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
За умови, що все налаштовано правильно, тепер ви отримаєте вітальну електронну пошту у свою поштову скриньку, надіслану вашим веб -додатком. Хороша робота! Ви пройшли довгий шлях. Я хотів додати, якщо ви взагалі боретеся з будь -якими помилками, працюючи над таким проектом, не соромтеся шукати відповіді та просити допомоги. Google, серед інших пошукових систем, є чудовими ресурсами для пошуку допомоги програмування. Просто шукайте помилку, яку ви отримуєте, і ви зможете побачити, як інші люди вирішують проблему. Крім того, ви можете зв’язатися зі мною, своїми педагогами (викладачами, професорами, репетиторами), будь -яких однолітків в Інтернеті, які доступні для програмування, або знову звернутися до цієї книги чи інших ресурсів, щоб знайти рішення проблем, які ви відчуваєте. Я розумію, що це непросто, але навіть якщо ви читали в цьому далеко і не пишете жодного коду, ви багато чого дізнаєтесь про створення веб -додатку з нуля. Погладьте по спині, ви чудово робитеробота. Дякуємо, що знайшли час, щоб прочитати цей посібник з веб -розробки третього видання. У майбутні видання я включу більше важливих прикладів, обговорених на початку документа, і ми зануримося набагато глибше у світ програмного забезпечення та розробки обладнання. Слідкуйте за тим, що має бути, і я з нетерпінням чекаю навчити вас створити неймовірне програмне забезпечення. До зустрічі в наступному






Закривати
Сторінка 1
Стрибати
Див. Повну статтю
Продовжуйте читати

купити | Купуйте за криптовалюту



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


(Натисніть або торкніться, щоб завантажити зображення)
Професійні розваги, фотографії, відео, аудіо, прямі трансляції та звичайні ігри, а також сканування документів, веб-розробка та послуги сурогатного материнства.

Залиште мені чайові в біткойнах за цією адресою: 3KhDWoSve2N627RiW8grj6XrsoPT7d6qyE

© Glam Girl X 2025

Умови обслуговування