Лайфхак – пишем и бесплатно хостим в облаке вебсайт с гостевой книгой

в 20:07, , рубрики: .net, asp.net core, C#, CloudFlare, guestbook, heroku, mongo, mongodb, recaptcha, гостевая книга

Хостим в облаке вебсайт с гостевой книгой бесплатно

В наше время развернуть свой домен первого уровня в облаке можно бесплатно. Не знаете как? Читайте дальше.

Предлагаю вам разобрать то, как можно создать гостевую книгу на ASP.NET Core (с reCAPTCHA) и захостить ее бесплатно на довольно известном облачном хостинге (да, с ограничениями, но для персонального вебсайта с не особо большим трафиком годится вполне)

В качестве базы данных мне по душе пришлась MongoDB от Atlas. Ее тоже можно "заюзать" бесплатно.
Альтернативно есть еще неплохие варианты в виде DynamoDB с какими-то бесплатными лимитами и Firebase Firestore.

Приложение будет докеризированно. Но так как "присутствует отсутствие желания" устанавливать докер локально, то настроим pipeline для автоматической сборки и публикации образа Docker-а (само-собой тоже бесплатно)

Сам исходник гостевой книги вы можете найти на github
Рассматривать код подробно не буду. Вкратце только рассмотрю добавление reCAPTCHA v3. Recaptcha для гостевой книги это Must. Причем, Recaptcha 3-ей версии не напрягает пользователя вводом символов.

Использование reCAPTCHA

Завести аккаунт и получить SiteKey и SecretKey можно в консоли админа Google reCAPTCHA.
Не забудьте добавить localhost (временно на время разработки) и url вашего вебсайта в список доменов (он находится в сеттингах)

Админка reCAPTCHA

Цепляем скрипт с ключиком взятым из сеттингов приложения в качестве параметра:

<script src="https://www.google.com/recaptcha/api.js?render=@Configuration["ReCaptcha:SiteKey"]" async defer></script>

И в событии отправки содержимого формы добавляем токен reCAPTCHA (отправляем без использования jQuery “ортодоксальным” XMLHttpRequest)

grecaptcha.ready(function() {
  grecaptcha.execute('@Configuration["ReCaptcha:SiteKey"]', {action: 'homepage'}).then(function(token) {
    xhttp.open('POST', '@Url.Action("AddMessage", "Home")', true);
    xhttp.setRequestHeader("RequestVerificationToken", 
    document.getElementById('RequestVerificationToken').value);
    var formData = new FormData(document.forms.message);
    formData.append("Token", token)
    xhttp.send(formData);
  });
});

В качестве заголовка устанавливается AntiForgeryToken. Это другой токен, без которого тоже никак.
Для того чтобы убедиться, что запрос не был отправлен роботом или спамером, необходимо отправить токен полученный от reCAPTCHA и секретный ключ на адрес www.google.com/recaptcha/api/siteverify

Для этого нам понадобится HttpClient. Создавать HttpClient используя конструкцию using совсем не в концепте ASP.NET Core. В Core принято создавать фабрику HttpClientFactory. Создается она просто. В Startup.cs добавляется строчка

services.AddHttpClient();

И затем уже в конструкторах контроллеров мы можем извлекать/создавать из DI экземпляры клиентов. Например, так:

private readonly HttpClient _httpClient;
public HomeController(IHttpClientFactory httpClientFactory)
{
  _httpClient = httpClientFactory.CreateClient("defaultClient");
}

Проверяем reCAPTCHA так:

var parameters = new Dictionary<string, string> {
                { "secret", _configuration["ReCaptcha:SecretKey"] },
                { "response", model.Token } };
var encodedContent = new FormUrlEncodedContent(parameters);
var response = await _httpClient.PostAsync("https://www.google.com/recaptcha/api/siteverify", encodedContent);
var result = JsonConvert.DeserializeObject<ReCaptchaResponse>(await response.Content.ReadAsStringAsync());

При этом сам класс ReCaptchaResponse:

public class ReCaptchaResponse
{
    public bool success { get; set; }
    public double score { get; set; }
    public string action { get; set; }
    public string hostname { get; set; }
    public string challenge_ts { get; set; }
}

Создание бесплатной облачной базы данных

При регистрации аккаунта в MongoDB Atlas.
Необходимо ввести номер телефона и еще какие-то персональные данные. Бесплатный Starter cluster предназначен для изучения MongoDB и для небольших приложений. Интересно то, что вы можете выбрать не только регион, но провайдера облачного хостинга вашей базы на свой вкус из трех самых крупных

Выбор региона и провайдера в MondoDB Atlas

После создания кластера вам необходимо будет создать пользователя

Создание пользователя

и придется добавить все IP с список разрешенных (к сожалению, бесплатный план хостинга Heroku не предоставляет статического IP).

Удар по безопасности в виде разрешения доступа со всех IP

Теперь нам остается только создать базу данных и коллекцию

Главный экран админки

Кликаем на COLLECTIONS и далее на Add my own data

Окно из которого можно создать коллекцию

Придумываем имя базы и коллекции и заполняем поля. Capped collections лучше не выбирать, так как в таком случае не получится удалять записи. Capped collections просто идеальны для логирования информации. Запись новых записей производится быстро, при достижении определенного объема происходит перезапись старых записей.

Создание коллекции

Кликнув на Connect и выбрав Connect Your Application

Получение строки подключения

Вы получите возможность скопировать строку подключения

Получение строки подключения

Создание приложения Heroku

Создание приложения на Heroku

Там все реально просто. Даже кредитку можно не привязывать при регистрации аккаунта.

Создание pipeline для публикации образа в Docker Hub

В проекте создадим Dockerfile с довольно обычным содержимым (приведен пример файла для версии .NET Core 2.2)

FROM mcr.microsoft.com/dotnet/core/aspnet:2.2-stretch-slim AS base
WORKDIR /app
EXPOSE 64498
EXPOSE 44396

FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
WORKDIR /src

COPY Guestbook.csproj Guestbook.csproj
RUN dotnet restore
COPY . .
WORKDIR /src
RUN dotnet build -c Release -o /app

FROM build AS publish
RUN dotnet publish -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "Guestbook.dll"]

Для того, чтобы Heroku смог запустить образ, последнюю строчку необходимо будет изменить на

CMD ASPNETCORE_URLS=http://*:$PORT dotnet Guestbook.dll

Исходный код необходимо запушить в какую-нибудь систему контроля версий. Я запушил в GitHub.
После того как код помещен в GitHub для сборки образа докера становится возможным использовать Azure Devops. Эту часть статьи вы можете промотать, установить Docker локально и пересобирать все каждый раз вручную.

Создание проекта опишу скринами

Создание проекта в Azure DevOps

После того как создадите сам проект необходимо создать новую pipeline

Создание Pipeline

и выбрать систему контроля версий которую вы используете

Выбор системы контроля версий

Теперь можно выбрать репозиторий

Выбор репозитория

Далее необходимо будет авторизовать DevOps для доступа к репозиторию.
И можно будет выбрать тип конфигурации (yaml файл определенного типа будет создан автоматически)

Выбор типа конфигурации

Наш вариант это Docker.
В открывшемся окошке нужно указать путь к Docker файлу:

Путь к докер файлу

На следующем шаге вам будет отображено содержимое yaml файла.

Можете подумать и поколдовать над ним сами, но проще скопировать следующий код и заменить в нем некоторые значения (Внимание! Пробелы в yaml очень важны):

variables:
  dockerId: your-docker-login  # Replace with your Docker ID for Docker Hub or the admin user name for the Azure Container Registry
  imageName: mongodb-guestbook  # Replace with the name of the image you want to publish

steps:
- script: |
    docker build -t $(dockerId)/$(imageName) .
    docker login -u $(dockerId) -p $(dockerPassword)
    docker push $(dockerId)/$(imageName)

    docker login --username=_ --password=$(token) registry.heroku.com

    docker build -t registry.heroku.com/myfreeguestbook/web .
    docker push registry.heroku.com/myfreeguestbook/web

your-docker-login вам нужно заменить на ID вашего аккаунта докера
mongodb-guestbook меняйте на имя вашего образа
вместо myfreeguestbook вставьте имя вашего приложения на Heroku

Останется ввести значения переменных dockerPassword и token. Для этого нужно нажать Variables

Кнопка Variables

Ну и ввести пароль от аккаунта докера. И токен..

Окно Variables

Если где взять пароль от аккаунта докера понятно, то для того чтобы получить токен нам понадобится Heroku CLI
Скачать ее можно по следующей ссылке: Download and install
Можно установить standalone/portable версию.

Вход осуществляется с помощью одной из следующих команд: heroku login (эта команда откроет окно браузера для логина) или heroku login -I (эта команда запросит пароль в консоли)

Токен получается с помощью команды

heroku auth:token

Также желательно изменить тип приложения Heroku на container. Делается это командой:

heroku stack:set container -a myfreeguestbook

Не забудьте изменить myfreeguestbook на имя вашего приложения.

После того как pipeline отработает и создаст образ докера необходимо выполнить команду публикующую ваше приложение:

heroku container:release -a myfreeguestbook

Если вы правильный разработчик и храните все сеттинги в файле appsettings.Development.json, то проект у вас не поднимется. Для того чтобы все заработало необходимо добавить сеттинги в Heroku

Значения конфигурации приложения Heroku

Дочерние элементы json отделяются двойными подчеркиваниями __

Настройка домена и SSL

С помощью Heroku CLI можно добавить ваш домен к приложению. Для этого предварительно придется привязать кредитку к аккаунту.

Команда:

heroku domains:add www.example.ru

Выдаст вам что-то вроде:

Adding www.example.ru to ⬢ example-app… done
▸ Configure your app's DNS provider to point to the DNS Target
▸ whispering-willow-5678.herokudns.com.
▸ For help, see https://devcenter.heroku.com/articles/custom-domains
Ее необходимо повторить для вашего root домена (например, для example.ru)

Псевдонимы CNAME необходимо сохранить и добавить в качестве CNAME на портале регистратора вашего доменного имени

www whispering-willow-erkie5ugksj4fo.herokudns.com

@ mighty-horse-dvkerbibi34biufbwiieuf.herokudns.com

Можно добавить их сразу в редактор произвольных записей DNS:

www.example.ru. IN CNAME whispering-willow-erkie5ugksj4fo.herokudns.com.

@.example.ru IN CNAME mighty-horse-dvkerbibi34biufbwiieuf.herokudns.com.

Можно сделать так.

Но мне больше по душе вариант завести бесплатный аккаунт в cloudflare. Ведь Cloudflare предоставляет бесплатный SSL сертификат. В качестве Content необходимо указать CNAME значения полученные от Heroku. У меня еще, как видите, добавлена и бесплатная Яндекс почта для домена.

Настройка CloudFlare

Ну а то, что будет указано в значениях Cloudflare nameservers вам нужно будет указать в виде DNS серверов на сайте вашего доменного регистратора.

В результате получится, что CloudFlare является посредником между вашим DNS провайдером и Heroku.

Автор: Алексей Соммер

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js