
рдЖрдЬрдХрд▓, рдЖрдк рдЕрдкрдиреА рд╡реЗрдмрд╕рд╛рдЗрдЯ рдХреЛ рдХреНрд▓рд╛рдЙрдб рдореЗрдВ рджреВрд╕рд░реЗ рд╕реНрддрд░ рдХреЗ рдбреЛрдореЗрди рдирд╛рдо рдХреЗ рд╕рд╛рде рдореБрдлреНрдд рдореЗрдВ рддреИрдирд╛рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдХреНрдпрд╛ рдЖрдк рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЙрддреНрд╕реБрдХ рд╣реИрдВ? рдкрд░ рдкрдврд╝реЗрдВред
рдореЗрд░рд╛ рд╕реБрдЭрд╛рд╡ рд╣реИ рдХрд┐ рдЖрдк рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓рддреЗ рд╣реИрдВ рдХрд┐ рдЖрдк ASP.NET Core (reCAPTCHA рдХреЗ рд╕рд╛рде) рдкрд░ рдПрдХ рдЕрддрд┐рдерд┐ рдкреБрд╕реНрддрдХ рдХреИрд╕реЗ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рдХрд╛рдлреА рдкреНрд░рд╕рд┐рджреНрдз рдХреНрд▓рд╛рдЙрдб рд╣реЛрд╕реНрдЯрд┐рдВрдЧ рдкрд░ рдореБрдлреНрдд рдореЗрдВ рд╣реЛрд╕реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рд╣рд╛рдБ, рд╕реАрдорд╛рдУрдВ рдХреЗ рд╕рд╛рде, рд▓реЗрдХрд┐рди рдпрд╣ рдПрдХ рдирд┐рдЬреА рд╡реЗрдмрд╕рд╛рдЗрдЯ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЙрдкрдпреБрдХреНрдд рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдЯреНрд░реИрдлрд╝рд┐рдХ рд╣реИ)
рдПрдХ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд░реВрдк рдореЗрдВ, рдореИрдВ рдПрдЯрд▓рд╕ рд╕реЗ MongoDB рдкрд╕рдВрдж рдЖрдпрд╛ред рдпрд╣ рдореБрдлреНрдд рдореЗрдВ "рдЬрд╝рд╛рдпреБрдЬрд╛рдд" рднреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИред
рд╡реИрдХрд▓реНрдкрд┐рдХ рд░реВрдк рд╕реЗ, рдХреБрдЫ рдкреНрд░рдХрд╛рд░ рдХреА рдореБрдлреНрдд рд╕реАрдорд╛ рдФрд░ рдлрд╛рдпрд░рдмреЗрд╕ рдлрд╛рдпрд░рд╕реНрдЯрд╛рд░ рдХреЗ рд╕рд╛рде рдбрд╛рдпрдирдореЛрдбреАрдмреА рдХреЗ рд░реВрдк рдореЗрдВ рдЕрднреА рднреА рдЕрдЪреНрдЫреЗ рд╡рд┐рдХрд▓реНрдк рд╣реИрдВред
рдЖрд╡реЗрджрди рдХреЛ рдбреЙрдХреНрдпреВрдореЗрдВрдЯ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рд▓реЗрдХрд┐рди рд╕реНрдерд╛рдиреАрдп рд░реВрдк рд╕реЗ рдбреЙрдХ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП "рдЗрдЪреНрдЫрд╛ рдХреА рдХрдореА рд╣реИ" рдХреЗ рдмрд╛рдж рд╕реЗ, рд╣рдо рдбреЙрдХрд░ рдЫрд╡рд┐ рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдмрдирд╛рдиреЗ рдФрд░ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВрдЧреЗ (рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдореБрдлреНрдд рднреА)
рдЖрдк рдЕрддрд┐рдерд┐ рдкреБрд╕реНрддрдХ рдХрд╛ рд╕реНрд░реЛрдд рдХреЛрдб github рдкрд░ рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВ
рдореИрдВ рдХреЛрдб рдкрд░ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рд╡рд┐рдЪрд╛рд░ рдирд╣реАрдВ рдХрд░реВрдВрдЧрд╛ред рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рдореИрдВ рд╕рд┐рд░реНрдл reCAPTCHA v3 рдХреЛ рдЬреЛрдбрд╝рдХрд░ рджреЗрдЦреВрдВрдЧрд╛ред рдЕрддрд┐рдерд┐ рдкреБрд╕реНрддрдХ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдЕрд╡рд╢реНрдп рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, Recaptcha 3rd рд╕рдВрд╕реНрдХрд░рдг рдЪрд░рд┐рддреНрд░ рдЗрдирдкреБрдЯ рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдкрд░реЗрд╢рд╛рди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред
ReCAPTCHA рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛
рдЖрдк Google рд╡реНрдпрд╡рд╕реНрдерд╛рдкрдХ рдХрдВрд╕реЛрд▓ reCAPTCHA рдореЗрдВ рдПрдХ рдЦрд╛рддрд╛ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ SiteKey рдФрд░ SecretKey рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рд▓реЛрдХрд▓рд╣реЛрд╕реНрдЯ (рдЕрд╕реНрдерд╛рдпреА рд░реВрдк рд╕реЗ рд╡рд┐рдХрд╛рд╕ рдХреЗ рд╕рдордп) рдФрд░ рдЕрдкрдиреА рд╡реЗрдмрд╕рд╛рдЗрдЯ рдХреЗ рдпреВрдЖрд░рдПрд▓ рдХреЛ рдбреЛрдореЗрди рдХреА рд╕реВрдЪреА рдореЗрдВ рдЬреЛрдбрд╝рдирд╛ рди рднреВрд▓реЗрдВ (рдпрд╣ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдореЗрдВ рд╣реИ)

рд╣рдо рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреА рд╕реЗрдЯрд┐рдВрдЧ рд╕реЗ рд▓реА рдЧрдИ рдХреБрдВрдЬреА рдХреЗ рд╕рд╛рде рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рд╣реБрдХ рдХрд░рддреЗ рд╣реИрдВ:
<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 рдмрдирд╛рдирд╛ ASP.NET рдХреЛрд░ рдЕрд╡рдзрд╛рд░рдгрд╛ рдореЗрдВ рдмрд┐рд▓реНрдХреБрд▓ рдирд╣реАрдВ рд╣реИред рдХреЛрд░ рдореЗрдВ, рдпрд╣ рдПрдХ HttpClientFactory рдХрд╛рд░рдЦрд╛рдирд╛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рдерд╛рдЧрдд рд╣реИред рдпрд╣ рдмрд╕ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред Startup.cs рдореЗрдВ рдПрдХ рдкрдВрдХреНрддрд┐ рдЬреЛрдбрд╝реА рдЬрд╛рддреА рд╣реИ
services.AddHttpClient();
рдФрд░ рдлрд┐рд░, рдирд┐рдпрдВрддреНрд░рдХреЛрдВ рдХреЗ рдбрд┐рдЬрд╛рдЗрдирд░реЛрдВ рдореЗрдВ, рд╣рдо рдбреАрдЖрдИ рд╕реЗ рдЧреНрд░рд╛рд╣рдХ рдЙрджрд╛рд╣рд░рдг рдирд┐рдХрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ / рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЗрд╕ рддрд░рд╣:
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 рдПрдЯрд▓рд╕ рдХреЗ рд╕рд╛рде рдПрдХ рдЦрд╛рддреЗ рдХрд╛ рдкрдВрдЬреАрдХрд░рдгред
рдЖрдкрдХреЛ рдПрдХ рдлрд╝реЛрди рдирдВрдмрд░ рдФрд░ рдХреБрдЫ рдЕрдиреНрдп рд╡реНрдпрдХреНрддрд┐рдЧрдд рдбреЗрдЯрд╛ рджрд░реНрдЬ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдореБрдХреНрдд рд╕реНрдЯрд╛рд░реНрдЯрд░ рдХреНрд▓рд╕реНрдЯрд░ рдХреЛ MongoDB рдФрд░ рдЫреЛрдЯреЗ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рд╕реАрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдпрд╣ рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ рдХрд┐ рдЖрдк рди рдХреЗрд╡рд▓ рдХреНрд╖реЗрддреНрд░ рдХрд╛ рдЪрдпрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдмрд▓реНрдХрд┐ рдЖрдкрдХреЗ рдЖрдзрд╛рд░ рдХреЗ рдХреНрд▓рд╛рдЙрдб рд╣реЛрд╕реНрдЯрд┐рдВрдЧ рдкреНрд░рджрд╛рддрд╛ рдЖрдкрдХреЗ рд╕реНрд╡рд╛рдж рдХреЗ рд▓рд┐рдП рддреАрди рд╕рдмрд╕реЗ рдмрдбрд╝реЗ рд╕реЗ

рдХреНрд▓рд╕реНрдЯрд░ рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рдПрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА

рдФрд░ рдЖрдкрдХреЛ рд╕рднреА IP рдХреЛ рдЕрдиреБрдордд рд╕реВрдЪреА рдХреЗ рд╕рд╛рде рдЬреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛ (рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рд╣рд░реЛрдХреВ рдХреА рдореБрдлреНрдд рд╣реЛрд╕реНрдЯрд┐рдВрдЧ рдпреЛрдЬрдирд╛ рдПрдХ рд╕реНрдерд┐рд░ рдЖрдИрдкреА рдкреНрд░рджрд╛рди рдирд╣реАрдВ рдХрд░рддреА рд╣реИ)ред

рдЕрдм рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рдбреЗрдЯрд╛рдмреЗрд╕ рдФрд░ рдПрдХ рд╕рдВрдЧреНрд░рд╣ рдмрдирд╛рдирд╛ рд╣реИ

COLLECTIONS рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВ рдФрд░ рдлрд┐рд░ Add my data рдкрд░

рд╣рдо рдбреЗрдЯрд╛рдмреЗрд╕ рдФрд░ рд╕рдВрдЧреНрд░рд╣ рдХреЗ рдирд╛рдо рдХреЗ рд╕рд╛рде рдЖрддреЗ рд╣реИрдВ рдФрд░ рдЦреЗрддреЛрдВ рдореЗрдВ рднрд░рддреЗ рд╣реИрдВред рдХреИрдкреНрдб рд╕рдВрдЧреНрд░рд╣ рдХрд╛ рдЪрдпрди рди рдХрд░рдирд╛ рдмреЗрд╣рддрд░ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рд░рд┐рдХреЙрд░реНрдбреНрд╕ рдХреЛ рд╣рдЯрд╛рдирд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реЛрдЧрд╛ред рдХреИрдкрд┐рдВрдЧ рд╕рдВрдЧреНрд░рд╣ рдЬрд╛рдирдХрд╛рд░реА рд▓реЙрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХрджрдо рд╕рд╣реА рд╣реИрдВред рдирдП рд░рд┐рдХреЙрд░реНрдб рдХреА рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ рддреНрд╡рд░рд┐рдд рд╣реИ, рдЬрдм рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд░рд╛рд╢рд┐ рддрдХ рдкрд╣реБрдБрдЪ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдкреБрд░рд╛рдиреЗ рд░рд┐рдХреЙрд░реНрдб рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦреЗ рдЬрд╛рддреЗ рд╣реИрдВред

рдХрдиреЗрдХреНрдЯ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рдХреЗ рдФрд░ рдХрдиреЗрдХреНрдЯ рдпреЛрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЪреБрдиреЗрдВ

рдЖрдк рдХрдиреЗрдХреНрд╢рди рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреА рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдмрдирд╛рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдВрдЧреЗ

рдПрдХ Heroku рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдмрдирд╛рдирд╛

рд╡рд╣рд╛рдБ рд╕рдм рдХреБрдЫ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╕рд░рд▓ рд╣реИред рдЦрд╛рддрд╛ рдкрдВрдЬреАрдХреГрдд рдХрд░рддреЗ рд╕рдордп рднреА рдХреНрд░реЗрдбрд┐рдЯ рдХрд╛рд░реНрдб рдирд╣реАрдВ рдмрд╛рдВрдзрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдбреЙрдХрд░ рд╣рдм рдореЗрдВ рдПрдХ рдЫрд╡рд┐ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдмрдирд╛рдирд╛
рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ, рдХрд╛рдлреА рд╕рд╛рдорд╛рдиреНрдп рд╕рд╛рдордЧреНрд░реА рдХреЗ рд╕рд╛рде рдПрдХ рдбреЙрдХрдлрд╛рдЗрд▓ рдмрдирд╛рдПрдВ (.NET рдХреЛрд░ 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"]
рд╣реЗрд░реЛрдХреВ рдХреЛ рдЫрд╡рд┐ рд▓реЙрдиреНрдЪ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП, рдЕрдВрддрд┐рдо рдкрдВрдХреНрддрд┐ рдХреЛ рдмрджрд▓рдирд╛ рд╣реЛрдЧрд╛
CMD ASPNETCORE_URLS=http://*:$PORT dotnet Guestbook.dll
рд╕реНрд░реЛрдд рдХреЛрдб рдХреЛ рдХреБрдЫ рд╕рдВрд╕реНрдХрд░рдг рдирд┐рдпрдВрддреНрд░рдг рдкреНрд░рдгрд╛рд▓реА рдореЗрдВ рдЪрд▓рд╛рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдореИрдВрдиреЗ рдЬреАрдердм рдкрд░ рд╢реБрд░реБрдЖрдд рдХреАред
рдПрдХ рдмрд╛рд░ рдЬрдм рдбреЙрдХрдЯрд░ рдЫрд╡рд┐ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП GitHub рдкрд░ рдХреЛрдб рд░рдЦрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ Azure Devops рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдЖрдк рд▓реЗрдЦ рдХреЗ рдЗрд╕ рд╣рд┐рд╕реНрд╕реЗ рдХреЛ рдЫреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ, рд╕реНрдерд╛рдиреАрдп рд░реВрдк рд╕реЗ рдбреЙрдХрд░ рдХреЛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рд╣рд░ рдмрд╛рд░ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рд╕рдм рдХреБрдЫ рдкреБрдирд░реНрдирд┐рд░реНрдорд╛рдг рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдореИрдВ рд╕реНрдХреНрд░реАрдирд╢реЙрдЯ рдХреЗ рд╕рд╛рде рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХрд╛ рд╡рд░реНрдгрди рдХрд░реВрдВрдЧрд╛

рд╕реНрд╡рдпрдВ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рдПрдХ рдирдИ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ

рдФрд░ рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛ рд░рд╣реЗ рд╕рдВрд╕реНрдХрд░рдг рдирд┐рдпрдВрддреНрд░рдг рдкреНрд░рдгрд╛рд▓реА рдХрд╛ рдЪрдпрди рдХрд░реЗрдВ

рдЕрдм рдЖрдк рдПрдХ рднрдВрдбрд╛рд░ рдХрд╛ рдЪрдпрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ

рдЗрд╕рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рднрдВрдбрд╛рд░ рдХреЛ рдПрдХреНрд╕реЗрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП DevOps рдХреЛ рдЕрдзрд┐рдХреГрдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
рдФрд░ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рдЪреБрдирдирд╛ рд╕рдВрднрд╡ рд╣реЛрдЧрд╛ (рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдкреНрд░рдХрд╛рд░ рдХреА рдпрд╛рдореНрд▓ рдлрд╝рд╛рдЗрд▓ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдмрдирд╛рдИ рдЬрд╛рдПрдЧреА)

рд╣рдорд╛рд░рд╛ рд╕рдВрд╕реНрдХрд░рдг рдбреЛрдХрд░ рд╣реИред
рдЦреБрд▓рдиреЗ рд╡рд╛рд▓реА рд╡рд┐рдВрдбреЛ рдореЗрдВ, рдЖрдкрдХреЛ рдбреЙрдХрд░ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдкрде рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдирд╛ рд╣реЛрдЧрд╛:

рдЕрдЧрд▓реЗ рдЪрд░рдг рдореЗрдВ, рдпрдорд▓ рдлрд╝рд╛рдЗрд▓ рдХреА рд╕рд╛рдордЧреНрд░реА рдЖрдкрдХреЛ рджрд┐рдЦрд╛рдИ рдЬрд╛рдПрдЧреАред
рдЖрдк рдЗрд╕реЗ рд╕реЛрдЪ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рд╕реНрд╡рдпрдВ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛрдб рдХреЛ рдХреЙрдкреА рдХрд░рдирд╛ рдФрд░ рдЗрд╕рдореЗрдВ рдХреБрдЫ рдореВрд▓реНрдпреЛрдВ рдХреЛ рдмрджрд▓рдирд╛ рдЖрд╕рд╛рди рд╣реИ (рдЕрдЯрдХрд▓реЗрдВ! рдпрд╛рдо рдореЗрдВ рд░рд┐рдХреНрдд рд╕реНрдерд╛рди рдмрд╣реБрдд рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИрдВ):
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
рдЖрдкрдХрд╛ docker-login рдЖрдкрдХреЛ рдЕрдкрдиреЗ docker рдЕрдХрд╛рдЙрдВрдЯ рдХреА рдЖрдИрдбреА рд╕реЗ рдмрджрд▓рдирд╛ рд╣реЛрдЧрд╛
mongodb-guestbook рдЖрдкрдХреА рдЫрд╡рд┐ рдХрд╛ рдирд╛рдо рдмрджрд▓ рджреЗрддрд╛ рд╣реИ
Myfreeguestbook рдХреЗ рдмрдЬрд╛рдп Heroku рдкрд░ рдЕрдкрдиреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛ рдирд╛рдо рдбрд╛рд▓реЗрдВ
рд╡рд╣ рд╕рдм рдХреБрдЫ рд╣реИ рдЬреЛ doCassassword рдФрд░ рдЯреЛрдХрди рд╡реИрд░рд┐рдПрдмрд▓ рдХреЗ рдорд╛рдиреЛрдВ рдХреЛ рджрд░реНрдЬ рдХрд░рддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЪрд░ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВ

рдареАрдХ рд╣реИ, рдбреЙрдХрдЯрд░ рдЦрд╛рддреЗ рдХреЗ рд▓рд┐рдП рдкрд╛рд╕рд╡рд░реНрдб рджрд░реНрдЬ рдХрд░реЗрдВред рдФрд░ рдЯреЛрдХрди редред

рдпрджрд┐ рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд╣реИ рдХрд┐ рдбреЙрдХрдЯрд░ рдЦрд╛рддреЗ рд╕реЗ рдкрд╛рд╕рд╡рд░реНрдб рдХрд╣рд╛рдБ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╣реИ, рддреЛ рдЯреЛрдХрди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдореЗрдВ рд╣рд░рдХреЛрд▓ рд╕реАрдПрд▓рдЖрдИ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ
рдЖрдк рдЗрд╕реЗ рдирд┐рдореНрди рд▓рд┐рдВрдХ рдкрд░ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ: рдбрд╛рдЙрдирд▓реЛрдб рдФрд░ рдЗрдВрд╕реНрдЯреЙрд▓ рдХрд░реЗрдВ
рдЖрдк рд╕реНрдЯреИрдВрдбрдЕрд▓реЛрди / рдкреЛрд░реНрдЯреЗрдмрд▓ рд╕рдВрд╕реНрдХрд░рдг рд╕реНрдерд╛рдкрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдирд┐рдореНрди рдЖрджреЗрд╢реЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ heroku login
: heroku login
(рдпрд╣ рдХрдорд╛рдВрдб рд▓реЙрдЧрд┐рди рдХреЗ рд▓рд┐рдП рдПрдХ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рд╡рд┐рдВрдбреЛ heroku login -I
) рдпрд╛ heroku login -I
(рдпрд╣ рдХрдорд╛рдВрдб рдХрдВрд╕реЛрд▓ рдореЗрдВ рдкрд╛рд╕рд╡рд░реНрдб рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд░реЗрдЧрд╛)
рдЖрджреЗрд╢ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЯреЛрдХрди рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ
heroku auth:token
рдпрд╣ рднреА рд╕рд▓рд╛рд╣ рджреА рдЬрд╛рддреА рд╣реИ рдХрд┐ рдХрдВрдЯреЗрдирд░ рдореЗрдВ рд╣рд░реЛрдХреВ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рдмрджрд▓рдирд╛ред рдпрд╣ рдХрдорд╛рдВрдб рджреНрд╡рд╛рд░рд╛ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:
heroku stack:set container -a myfreeguestbook
рдЕрдкрдиреЗ рдЖрд╡реЗрджрди рдХреЗ рдирд╛рдо рдкрд░ myfreeguestbook рдмрджрд▓рдирд╛ рдпрд╛рдж рд░рдЦреЗрдВред
рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдкреВрд░реА рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж рдФрд░ docker рдХреА рдЫрд╡рд┐ рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рдЕрдкрдиреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓реА рдХрдорд╛рдВрдб рдЪрд▓рд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:
heroku container:release -a myfreeguestbook
рдпрджрд┐ рдЖрдк рд╕рд╣реА рдбреЗрд╡рд▓рдкрд░ рд╣реИрдВ рдФрд░ appsettings.Development.json рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╕рднреА рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдЖрдкрдХреЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ред рд╕рдм рдХреБрдЫ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рд╣рд░реЛрдХреВ рдореЗрдВ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ

Json рдмрд╛рд▓ рддрддреНрд╡реЛрдВ рдХреЛ рдбрдмрд▓ рдЕрдВрдбрд░рд╕реНрдХреЛрд░ рджреНрд╡рд╛рд░рд╛ рдЕрд▓рдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ __
рдбреЛрдореЗрди рдФрд░ рдПрд╕рдПрд╕рдПрд▓ рд╕реЗрдЯрдЕрдк
рд╣рд░реЛрдХреВ рд╕реАрдПрд▓рдЖрдИ рдХреЗ рд╕рд╛рде, рдЖрдк рдЕрдкрдиреЗ рдбреЛрдореЗрди рдХреЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ рдЕрдкрдиреЗ рдЦрд╛рддреЗ рдореЗрдВ рдПрдХ рдХреНрд░реЗрдбрд┐рдЯ рдХрд╛рд░реНрдб рд╕рдВрд▓рдЧреНрди рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
рдЯреАрдо:
heroku domains:add www.example.ru
рдпрд╣ рдЖрдкрдХреЛ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджреЗрдЧрд╛:
Www.example.ru рдХреЛ-рдЙрджрд╛рд╣рд░рдг-рдРрдк рдореЗрдВ рдЬреЛрдбрд╝рдХрд░ ... рдХрд┐рдпрд╛ рдЧрдпрд╛
тЦ╕ рдбреАрдПрдирдПрд╕ рд▓рдХреНрд╖реНрдп рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреЗ рдРрдк рдХреЗ рдбреАрдПрдирдПрд╕ рдкреНрд░рджрд╛рддрд╛ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВ
Ing рдХрд╛рдирд╛рдлреВрд╕реА-willow-5678.herokudns.com
Oku рдорджрдж рдХреЗ рд▓рд┐рдП, https://devcenter.heroku.com/articles/custom-domains рджреЗрдЦреЗрдВ
рдЗрд╕реЗ рдЖрдкрдХреЗ рд░реВрдЯ рдбреЛрдореЗрди рдХреЗ рд▓рд┐рдП рджреЛрд╣рд░рд╛рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП ред.ru)
CNAME рдЙрдкрдирд╛рдореЛрдВ рдХреЛ рдЖрдкрдХреЗ рдбреЛрдореЗрди рдирд╛рдо рдкрдВрдЬреАрдпрдХ рдкреЛрд░реНрдЯрд▓ рдкрд░ CNAME рдХреЗ тАЛтАЛрд░реВрдк рдореЗрдВ рд╕рд╣реЗрдЬрд╛ рдФрд░ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП
www рдХрд╛рдирд╛рдлреВрд╕реА-willow-erkie5ugksj4fo.herokudns.com
@ mighty-horse-dvkerbibi34biufbwiieuf.herokudns.com
рдЖрдк рдЙрдиреНрд╣реЗрдВ рд╕реАрдзреЗ рдбреАрдПрдирдПрд╕ рд░рд┐рдХреЙрд░реНрдб рд╕рдВрдкрд╛рджрдХ рдХреА рдордирдорд╛рдиреА рд╕реЗ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ:
www.example.ru. IN CNAME whispering-willow-erkie5ugksj4fo.herokudns.com.
@.example.ru IN CNAME mighty-horse-dvkerbibi34biufbwiieuf.herokudns.com.
рдЖрдк рдРрд╕рд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рд▓реЗрдХрд┐рди рдореИрдВ рдПрдХ рдореБрдлреНрдд рдХреНрд▓рд╛рдЙрдбрдлрд╝реЗрдпрд░ рдЦрд╛рддрд╛ рд╣реЛрдиреЗ рдХреЗ рд╡рд┐рдХрд▓реНрдк рдХреЛ рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рджреЗрддрд╛ рд╣реВрдВред рдЖрдЦрд┐рд░рдХрд╛рд░, Cloudflare рдПрдХ рдирд┐рд╢реБрд▓реНрдХ SSL рдкреНрд░рдорд╛рдгрдкрддреНрд░ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рд╕рд╛рдордЧреНрд░реА рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рд╣рд░реЛрдХреВ рд╕реЗ рдкреНрд░рд╛рдкреНрдд CNAME рдорд╛рди рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдореИрдВрдиреЗ рдбреЛрдореЗрди рдХреЗ рд▓рд┐рдП рдореБрдлреНрдд рдпреИрдВрдбреЗрдХреНрд╕ рдореЗрд▓ рднреА рдЬреЛрдбрд╝рд╛ред

рдЦреИрд░, рдХреНрд▓рд╛рдЙрдбрдлреНрд▓реЗрдпрд░ рдиреЗрдорд╡реЗрд░рд░реНрд╕ рдХреЗ рдореВрд▓реНрдпреЛрдВ рдореЗрдВ рдХреНрдпрд╛ рд╕рдВрдХреЗрдд рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЖрдкрдХреЛ рдЕрдкрдиреЗ рдбреЛрдореЗрди рд░рдЬрд┐рд╕реНрдЯреНрд░рд╛рд░ рдХреА рд╕рд╛рдЗрдЯ рдкрд░ DNS рд╕рд░реНрд╡рд░реЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
рдкрд░рд┐рдгрд╛рдо рдпрд╣ рд╣реИ рдХрд┐ CloudFlare рдЖрдкрдХреЗ DNS рдкреНрд░рджрд╛рддрд╛ рдФрд░ Heroku рдХреЗ рдмреАрдЪ рдПрдХ рдордзреНрдпрд╕реНрде рд╣реИред