Лайфхак – пишем и бесплатно хостим в облаке вебсайт с гостевой книгой
В наше время для того, чтобы развернуть свой сайт в облаке достаточно купить доменное имя. Не верите? Читайте дальше.
Предлагаю вам разобрать то, как можно создать гостевую книгу на ASP.NET Core (с reCAPTCHA) и захостить ее бесплатно на довольно известном облачном хостинге (да, с ограничениями, но для персонального вебсайта с не особо большим трафиком годится вполне)
В качестве базы данных мне по душе пришлась MongoDB от Atlas. Ее тоже можно «заюзать» бесплатно.
Альтернативно есть еще неплохие варианты в виде DynamoDB с какими-то бесплатными лимитами и Firebase Firestore.
Приложение будет докеризированно. Но так как «присутствует отсутствие желания» устанавливать докер локально, то настроим pipeline для автоматической сборки и публикации образа Docker-а (само-собой тоже бесплатно)
Сам исходник гостевой книги вы можете найти на github
Рассматривать код подробно не буду. Вкратце только рассмотрю добавление reCAPTCHA v3. Recaptcha для гостевой книги это Must. Причем, Recaptcha 3-ей версии не напрягает пользователя вводом символов.
Завести аккаунт и получить SiteKey и SecretKey можно в консоли админа Google reCAPTCHA.
Не забудьте добавить localhost (временно на время разработки) и url вашего вебсайта в список доменов (он находится в сеттингах)
Цепляем скрипт с ключиком взятым из сеттингов приложения в качестве параметра:
И в событии отправки содержимого формы добавляем токен 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 {
{ "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(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 и для небольших приложений. Интересно то, что вы можете выбрать не только регион, но провайдера облачного хостинга вашей базы на свой вкус из трех самых крупных
После создания кластера вам необходимо будет создать пользователя
и придется добавить все IP с список разрешенных (к сожалению, бесплатный план хостинга Heroku не предоставляет статического IP).
Теперь нам остается только создать базу данных и коллекцию
Кликаем на COLLECTIONS и далее на Add my own data
Придумываем имя базы и коллекции и заполняем поля. Capped collections лучше не выбирать, так как в таком случае не получится удалять записи. Capped collections просто идеальны для логирования информации. Запись новых записей производится быстро, при достижении определенного объема происходит перезапись старых записей.
Кликнув на Connect и выбрав Connect Your Application
Вы получите возможность скопировать строку подключения
Там все реально просто. Даже кредитку можно не привязывать при регистрации аккаунта.
В проекте создадим 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 локально и пересобирать все каждый раз вручную.
Создание проекта опишу скринами
После того как создадите сам проект необходимо создать новую 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
Ну и ввести пароль от аккаунта докера. И токен…
Если где взять пароль от аккаунта докера понятно, то для того чтобы получить токен нам понадобится 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
Дочерние элементы json отделяются двойными подчеркиваниями __
С помощью 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 nameservers вам нужно будет указать в виде DNS серверов на сайте вашего доменного регистратора.
В результате получится, что CloudFlare является посредником между вашим DNS провайдером и Heroku.