Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
00341 005451 19039952 na godz. na dobę w sumie
ASP.NET Core 2.0. Wprowadzenie - książka
ASP.NET Core 2.0. Wprowadzenie - książka
Autor: , Liczba stron: 408
Wydawca: Helion Język publikacji: polski
ISBN: 978-83-283-4499-0 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> programowanie >> inne - programowanie
Porównaj ceny (książka, ebook (-35%), audiobook).

Framework ASP.NET Core 2.0 stanowi odpowiedź Microsoftu na potrzeby programistów, które z kolei zmieniają się wraz z rynkiem IT. Klienci wymagają od aplikacji zgodności z różnymi standardami, wysokiej efektywności i skalowalności, a czas wyprodukowania i wdrożenia nowego rozwiązania ma być jak najkrótszy. Do takiej pracy potrzeba narzędzi o odpowiedniej produktywności, rozszerzalności i elastyczności. Dzięki uwzględnieniu tych wyśrubowanych kryteriów Microsoft stworzył platformę ASP.NET Core pozwalającą na tworzenie, kompilację i uruchamianie aplikacji w dowolnym środowisku. Można też korzystać z zewnętrznych bibliotek i z najbardziej aktualnych wzorców projektowych. Opanowanie tego złożonego narzędzia pozwoli zająć programiście znakomitą pozycję wyjściową do tworzenia wydajnych i nowoczesnych aplikacji internetowych.

Ta książka jest przeznaczona dla programistów chcących budować nowoczesne aplikacje internetowe na platformie ASP.NET Core 2.0. W przystępny i zrozumiały sposób, na praktycznych przykładach wyjaśniono tu możliwości ASP.NET Core 2.0. Większość kluczowych funkcji została opisana z wykorzystaniem zwięzłych przykładów. Dzięki jasnym instrukcjom krok po kroku możliwe jest niemal natychmiastowe rozpoczęcie programowania. W książce omówiono tworzenie responsywnych aplikacji internetowych, stosowanie w praktyce modelu MVC, wdrażanie aplikacji z wykorzystaniem technologii chmury, a także monitorowanie pracy oprogramowania w środowisku produkcyjnym i reagowanie na pojawiające się problemy.

W tej książce między innymi:

ASP.NET Core 2.0. Podejmij wyzwanie!

Znajdź podobne książki Ostatnio czytane w tej kategorii

Darmowy fragment publikacji:

Tytuł oryginału: Learning ASP.NET Core 2.0 Tłumaczenie: Krzysztof Bąbol ISBN: 978-83-283-4499-0 Copyright © Packt Publishing 2017. First published in the English language under the title ‘Learning ASP.NET Core 2.0 – (9781788476638)’ Polish edition copyright © 2018 by Helion SA All rights reserved. All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from the Publisher. Wszelkie prawa zastrzeżone. Nieautoryzowane rozpowszechnianie całości lub fragmentu niniejszej publikacji w jakiejkolwiek postaci jest zabronione. Wykonywanie kopii metodą kserograficzną, fotograficzną, a także kopiowanie książki na nośniku filmowym, magnetycznym lub innym powoduje naruszenie praw autorskich niniejszej publikacji. Wszystkie znaki występujące w tekście są zastrzeżonymi znakami firmowymi bądź towarowymi ich właścicieli. Autor oraz HELION SA dołożyli wszelkich starań, by zawarte w tej książce informacje były kompletne i rzetelne. Nie biorą jednak żadnej odpowiedzialności ani za ich wykorzystanie, ani za związane z tym ewentualne naruszenie praw patentowych lub autorskich. Autor oraz Wydawnictwo HELION nie ponoszą również żadnej odpowiedzialności za ewentualne szkody wynikłe z wykorzystania informacji zawartych w książce. HELION SA ul. Kościuszki 1c, 44-100 GLIWICE tel. 32 231 22 19, 32 230 98 63 e-mail: helion@helion.pl WWW: http://helion.pl (księgarnia internetowa, katalog książek) Pliki z przykładami omawianymi w książce można znaleźć pod adresem: ftp://ftp.helion.pl/przyklady/asp2wp.zip Drogi Czytelniku! Jeżeli chcesz ocenić tę książkę, zajrzyj pod adres http://helion.pl/user/opinie/asp2wp Możesz tam wpisać swoje uwagi, spostrzeżenia, recenzję. Printed in Poland. • Kup książkę • Poleć książkę • Oceń książkę • Księgarnia internetowa • Lubię to! » Nasza społeczność Spis tre(cid:258)ci Przedmowa O autorach O recenzencie Wst(cid:218)p Rozdzia(cid:239) 1. Czym jest ASP.NET Core 2.0? Mo(cid:285)liwo(cid:258)ci ASP.NET Core 2.0 Wsparcie wielu platform Architektura mikrous(cid:239)ug Praca z platform(cid:200) Docker i kontenerami Wydajno(cid:258)(cid:202) i skalowalno(cid:258)(cid:202) Równoleg(cid:239)a instalacja ró(cid:285)nych wersji Ograniczenia technologii Kiedy wybra(cid:202) ASP.NET Core 2.0 Podsumowanie Rozdzia(cid:239) 2. Przygotowanie (cid:258)rodowiska (cid:165)rodowisko programistyczne Visual Studio 2017 Jak zainstalowa(cid:202) program Visual Studio 2017 Community Edition (cid:165)rodowisko programistyczne Visual Studio Code Jak zainstalowa(cid:202) program Visual Studio Code w systemie Linux Podsumowanie 7 11 12 13 23 25 26 27 28 29 29 29 31 32 33 34 35 46 47 55 Poleć książkęKup książkę Spis tre(cid:286)ci Rozdzia(cid:239) 3. Tworzenie potoku ci(cid:200)g(cid:239)ej integracji w us(cid:239)udze VSTS Potoki ci(cid:200)g(cid:239)ej integracji, ci(cid:200)g(cid:239)ego wdra(cid:285)ania oraz kompilowania i wydawania Organizacja pracy za pomoc(cid:200) elementów roboczych U(cid:285)ywanie systemu kontroli wersji Git Tworzenie potoku kompilowania w us(cid:239)udze VSTS Tworzenie potoku wydawania w us(cid:239)udze VSTS Podsumowanie Rozdzia(cid:239) 4. Podstawowe za(cid:239)o(cid:285)enia ASP.NET Core 2.0 — cz(cid:218)(cid:258)(cid:202) I Tworzenie gry Kó(cid:239)ko i krzy(cid:285)yk Adresowanie ró(cid:285)nych wersji platformy .NET Framework w plikach projektów .csproj U(cid:285)ywanie metapakietu Microsoft.AspNetCore.All Praca z klas(cid:200) Program Praca z klas(cid:200) Startup Nadawanie stronom WWW bardziej nowoczesnego wygl(cid:200)du za pomoc(cid:200) programu Bower i stron uk(cid:239)adu U(cid:285)ycie wstrzykiwania zale(cid:285)no(cid:258)ci dla wsparcia lu(cid:283)nych powi(cid:200)za(cid:241) w aplikacjach Praca z oprogramowaniem po(cid:258)rednicz(cid:200)cym Praca z plikami statycznymi U(cid:285)ywanie routingu, przekierowania URL oraz ponownego zapisywania adresów URL Dodawanie obs(cid:239)ugi b(cid:239)(cid:218)dów do aplikacji Podsumowanie Rozdzia(cid:239) 5. Podstawowe za(cid:239)o(cid:285)enia ASP.NET Core 2.0 — cz(cid:218)(cid:258)(cid:202) II Programowanie po stronie klienta za pomoc(cid:200) skryptów JavaScript Optymalizacja aplikacji internetowych oraz korzystanie z pakietów skryptów i ich minimalizacji Praca z protoko(cid:239)em WebSockets w scenariuszach komunikacji w czasie rzeczywistym Korzystanie z zarz(cid:200)dzania pami(cid:218)ci(cid:200) podr(cid:218)czn(cid:200) sesji i u(cid:285)ytkownika Stosowanie globalizacji i lokalizacji w wieloj(cid:218)zycznych interfejsach u(cid:285)ytkownika Konfiguracja aplikacji i us(cid:239)ug Korzystanie z logowania Implementacja zaawansowanych koncepcji wstrzykiwania zale(cid:285)no(cid:258)ci Jednoczesna kompilacja dla wielu (cid:258)rodowisk Podsumowanie Rozdzia(cid:239) 6. Tworzenie aplikacji MVC Zrozumienie wzorca Model-Widok-Kontroler Tworzenie uk(cid:239)adów przeznaczonych dla wielu urz(cid:200)dze(cid:241) Korzystanie ze stron widoku, widoków cz(cid:218)(cid:258)ciowych, sk(cid:239)adników widoku i pomocników znaczników Podzia(cid:239) aplikacji internetowych na wiele obszarów Stosowanie zaawansowanych koncepcji Podsumowanie 4 57 58 62 67 76 79 82 83 84 88 90 91 93 100 107 111 116 117 120 124 125 126 136 140 145 149 161 165 176 182 186 189 190 192 198 215 218 234 Poleć książkęKup książkę Spis tre(cid:286)ci Rozdzia(cid:239) 7. Tworzenie aplikacji Web API Stosowanie koncepcji Web API oraz najlepszych rozwi(cid:200)za(cid:241) w tej dziedzinie Podsumowanie Rozdzia(cid:239) 8. Dost(cid:218)p do danych za pomoc(cid:200) Entity Framework Core Rozpocz(cid:218)cie pracy z platform(cid:200) Entity Framework Core 2 Podsumowanie Rozdzia(cid:239) 9. Zabezpieczanie aplikacji ASP.NET Core 2.0 Implementacja uwierzytelniania Podsumowanie Rozdzia(cid:239) 10. Hosting i wdra(cid:285)anie aplikacji ASP.NET Core 2.0 Hosting aplikacji Wdra(cid:285)anie aplikacji na platformie Amazon Web Services Wdra(cid:285)anie aplikacji na platformie Microsoft Azure Wdra(cid:285)anie aplikacji w kontenerach Docker Podsumowanie Rozdzia(cid:239) 11. Zarz(cid:200)dzanie aplikacjami ASP.NET Core 2.0 i nadzór nad nimi Logowanie w aplikacjach ASP.NET Core 2.0 Monitorowanie aplikacji ASP.NET Core 2.0 Podsumowanie Skorowidz 235 236 264 265 266 276 277 278 326 327 328 329 348 361 368 371 372 382 401 403 5 Poleć książkęKup książkę Spis tre(cid:286)ci 6 Poleć książkęKup książkę 9 Zabezpieczanie aplikacji ASP.NET Core 2.0 W dzisiejszym (cid:258)wiecie przy wzro(cid:258)cie liczby przest(cid:218)pstw komputerowych i oszustw interne- towych wszystkie nowoczesne aplikacje WWW wymagaj(cid:200) implementacji silnych mechanizmów bezpiecze(cid:241)stwa w celu zapobiegania atakom i przyw(cid:239)aszczeniu to(cid:285)samo(cid:258)ci u(cid:285)ytkowników. Do tej pory skupiali(cid:258)my si(cid:218) na poznaniu metod tworzenia efektywnych aplikacji interneto- wych na platformie ASP.NET Core 2.0, nie my(cid:258)l(cid:200)c wcale o uwierzytelnianiu i autoryzacji u(cid:285)ytkowników ani ochronie danych, ale poniewa(cid:285) aplikacja Kó(cid:239)ko i krzy(cid:285)yk staje si(cid:218) coraz bardziej skomplikowana, to przed ko(cid:241)cowym, ogólnodost(cid:218)pnym wdro(cid:285)eniem musimy si(cid:218) za- j(cid:200)(cid:202) sprawami bezpiecze(cid:241)stwa. Tworzenie aplikacji internetowej bez my(cid:258)lenia o bezpiecze(cid:241)stwie jest wielkim niedoci(cid:200)gni(cid:218)ciem i mo(cid:285)e doprowadzi(cid:202) do upadku nawet najwi(cid:218)ksze i najbardziej znane witryny. W przypadku naruszenia bezpiecze(cid:241)stwa i kradzie(cid:285)y danych osobowych z(cid:239)a reputacja i uderzenie w zaufa- nie u(cid:285)ytkowników s(cid:200) olbrzymie i nikt nie chce wi(cid:218)cej mie(cid:202) do czynienia z takimi aplikacjami, a co gorsza — firmami. To zagadnienie musi by(cid:202) traktowane bardzo powa(cid:285)nie. Nale(cid:285)y pracowa(cid:202) z firmami zajmuj(cid:200)- cymi si(cid:218) bezpiecze(cid:241)stwem w celu weryfikacji kodu i przeprowadzania testów penetracyjnych, aby zapewni(cid:202) zgodno(cid:258)(cid:202) z najlepszymi rozwi(cid:200)zaniami i wysokimi standardami bezpiecze(cid:241)stwa (na przyk(cid:239)ad OWASP10). Na szcz(cid:218)(cid:258)cie platforma ASP.NET Core 2.0 zawiera wszystko, co potrzebne, aby pomóc w tym wa(cid:285)nym — cho(cid:202) skomplikowanym — zagadnieniu. Wi(cid:218)kszo(cid:258)(cid:202) wbudowanych w ni(cid:200) funkcji nie wymaga nawet zaawansowanej umiej(cid:218)tno(cid:258)ci programowania ani znajomo(cid:258)ci kwestii bez- piecze(cid:241)stwa. Zobaczysz, (cid:285)e dzi(cid:218)ki u(cid:285)yciu frameworka Identity platformy ASP.NET Core 2.0 poznanie i implementacja bezpiecznych aplikacji s(cid:200) bardzo proste. Poleć książkęKup książkę ASP.NET Core 2.0. Wprowadzenie W tym rozdziale poruszymy nast(cid:218)puj(cid:200)ce zagadnienia: (cid:81) wprowadzanie podstawowego uwierzytelniania za pomoc(cid:200) formularza; (cid:81) wprowadzanie uwierzytelniania za po(cid:258)rednictwem zewn(cid:218)trznego dostawcy; (cid:81) dodawanie mechanizmu resetowania zapomnianego has(cid:239)a; (cid:81) praca z uwierzytelnianiem dwusk(cid:239)adnikowym; (cid:81) implementacja autoryzacji. Implementacja uwierzytelniania Uwierzytelnianie pozwala na identyfikacj(cid:218) w aplikacji konkretnego u(cid:285)ytkownika. Nie u(cid:285)ywa si(cid:218) go do zarz(cid:200)dzania prawami dost(cid:218)pu u(cid:285)ytkowników, bo to jest rola autoryzacji, ani do ochrony danych. Istnieje kilka metod uwierzytelniania u(cid:285)ytkowników aplikacji, takich jak: (cid:81) podstawowe uwierzytelnianie za pomoc(cid:200) formularza logowania z polami loginu i has(cid:239)a; (cid:81) uwierzytelnianie przez pojedyncze logowanie (ang. Single Sign-On — SSO), w przypadku którego u(cid:285)ytkownik uwierzytelnia si(cid:218) tylko raz do wszystkich aplikacji w ramach swojej firmy; (cid:81) uwierzytelnianie za po(cid:258)rednictwem zewn(cid:218)trznego dostawcy w sieciach spo(cid:239)eczno(cid:258)ciowych (takich jak Facebook i LinkedIn); (cid:81) uwierzytelnianie za pomoc(cid:200) certyfikatów lub infrastruktury klucza publicznego (ang. public key infrastructure — PKI). Platforma ASP.NET Core 2.0 obs(cid:239)uguje te wszystkie metody, ale w tym rozdziale skoncentrujemy si(cid:218) na uwierzytelnianiu za pomoc(cid:200) formularzy z loginem u(cid:285)ytkownika i has(cid:239)em oraz na uwie- rzytelnianiu za po(cid:258)rednictwem zewn(cid:218)trznego dostawcy — serwisu Facebook. W kolejnych przyk(cid:239)adach przyjrzysz si(cid:218) u(cid:285)yciu tych metod do uwierzytelniania u(cid:285)ytkowników aplikacji, a tak(cid:285)e bardziej zaawansowanym mo(cid:285)liwo(cid:258)ciom, na przyk(cid:239)ad mechanizmom po- twierdzania adresu e-mail oraz resetowania has(cid:239)a. Na koniec zobaczysz, jak w przypadku kluczowych aplikacji za pomoc(cid:200) funkcji wbudowanych w platform(cid:218) ASP.NET Core 2.0 zaimplementowa(cid:202) uwierzytelnianie dwusk(cid:239)adnikowe. Przygotujmy implementacj(cid:218) ró(cid:285)nych mechanizmów uwierzytelniania w aplikacji Kó(cid:239)ko i krzy(cid:285)yk: 1. W klasie Startup zmie(cid:241) czas istnienia instancji UserService, GameInvitationService i GameSessionService: services.AddTransient IUserService, UserService (); services.AddScoped IGameInvitationService, GameInvitationService (); services.AddScoped IGameSessionService, GameSessionService (); 278 Poleć książkęKup książkę Rozdzia(cid:225) 9. • Zabezpieczanie aplikacji ASP.NET Core 2.0 2. Zmie(cid:241) metod(cid:218) Configure klasy Startup, dodaj(cid:200)c zaraz po oprogramowaniu po(cid:258)rednicz(cid:200)cym plików statycznych wywo(cid:239)anie oprogramowania po(cid:258)rednicz(cid:200)cego uwierzytelniania: app.UseStaticFiles(); app.UseAuthentication(); 3. Zmie(cid:241) klas(cid:218) UserModel, aby dostosowa(cid:202) j(cid:200) do funkcji uwierzytelniania wybudowanych we framework Identity platformy ASP.NET Core 2.0, usuwaj(cid:200)c w(cid:239)a(cid:258)ciwo(cid:258)ci Id i Email, które ma ju(cid:285) klasa IdentityUser: public class UserModel : IdentityUser Guid { [Display(Name = FirstName )] [Required(ErrorMessage = FirstNameRequired )] public string FirstName { get; set; } [Display(Name = LastName )] [Required(ErrorMessage = LastNameRequired )] public string LastName { get; set; } [Display(Name = Password )] [Required(ErrorMessage = PasswordRequired ), DataType(DataType.Password)] public string Password { get; set; } [NotMapped] public bool IsEmailConfirmed { get { return EmailConfirmed; } } public System.DateTime? EmailConfirmationDate { get; set; } public int Score { get; set; } } W rzeczywistych zastosowaniach nale(cid:285)a(cid:239)oby usun(cid:200)(cid:202) równie(cid:285) w(cid:239)a(cid:258)ciwo(cid:258)(cid:202) Password, jednak dla przejrzysto(cid:258)ci i w celach edukacyjnych w tym przyk(cid:239)adzie j(cid:200) pozostawimy. 4. Dodaj folder o nazwie Managers, a w nim klas(cid:218) ApplicationUserManager: public class ApplicationUserManager : UserManager UserModel { private IUserStore UserModel _store; DbContextOptions GameDbContext _dbContextOptions; public ApplicationUserManager( DbContextOptions GameDbContext dbContextOptions, IUserStore UserModel store, IOptions IdentityOptions optionsAccessor, IPasswordHasher UserModel passwordHasher, IEnumerable IUserValidator UserModel userValidators, IEnumerable IPasswordValidator UserModel passwordValidators, ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors, IServiceProvider services, ILogger UserManager UserModel logger) : base(store, optionsAccessor, passwordHasher, 279 Poleć książkęKup książkę ASP.NET Core 2.0. Wprowadzenie userValidators, passwordValidators, keyNormalizer, errors, services, logger) { _store = store; _dbContextOptions = dbContextOptions; } public override async Task UserModel FindByEmailAsync( string email) { using (var dbContext = new GameDbContext(_dbContextOptions)) { return await dbContext.Set UserModel ().FirstOrDefaultAsync( x = x.Email == email); } } public override async Task UserModel FindByIdAsync( string userId) { using (var dbContext = new GameDbContext(_dbContextOptions)) { Guid id = Guid.Parse(userId); return await dbContext.Set UserModel ().FirstOrDefaultAsync( x = x.Id == id); } } public override async Task IdentityResult UpdateAsync(UserModel user) { using (var dbContext = new GameDbContext(_dbContextOptions)) { var current = await dbContext.Set UserModel ().FirstOrDefaultAsync(x = x.Id == user.Id); current.AccessFailedCount = user.AccessFailedCount; current.ConcurrencyStamp = user.ConcurrencyStamp; current.Email = user.Email; current.EmailConfirmationDate = user.EmailConfirmationDate; current.EmailConfirmed = user.EmailConfirmed; current.FirstName = user.FirstName; current.LastName = user.LastName; current.LockoutEnabled = user.LockoutEnabled; current.NormalizedEmail = user.NormalizedEmail; current.NormalizedUserName = user.NormalizedUserName; current.PhoneNumber = user.PhoneNumber; current.PhoneNumberConfirmed = user.PhoneNumberConfirmed; current.Score = user.Score; current.SecurityStamp = user.SecurityStamp; current.TwoFactorEnabled = user.TwoFactorEnabled; current.UserName = user.UserName; await dbContext.SaveChangesAsync(); 280 Poleć książkęKup książkę Rozdzia(cid:225) 9. • Zabezpieczanie aplikacji ASP.NET Core 2.0 return IdentityResult.Success; } } public override async Task IdentityResult ConfirmEmailAsync(UserModel user, string token) { var isValide = await base.VerifyUserTokenAsync(user, Options.Tokens.EmailConfirmationTokenProvider, ConfirmEmailTokenPurpose, token); if (isValide) { using (var dbContext = new GameDbContext(_dbContextOptions)) { var current = await dbContext.UserModels.FindAsync(user.Id); current.EmailConfirmationDate = DateTime.Now; current.EmailConfirmed = true; await dbContext.SaveChangesAsync(); return IdentityResult.Success; } } return IdentityResult.Failed(); } } 5. W klasie Startup zarejestruj instancj(cid:218) ApplicationUserManager: services.AddTransient ApplicationUserManager (); 6. Dostosuj us(cid:239)ug(cid:218) UserService do wspó(cid:239)pracy z klas(cid:200) ApplicationUserManager, dodaj dwie metody GetEmailConfirmationCode i ConfirmEmail oraz uaktualnij interfejs IUserService: public class UserService { private ILogger UserService _logger; private ApplicationUserManager _userManager; public UserService(ApplicationUserManager userManager, ILogger UserService logger) { _userManager = userManager; _logger = logger; var emailTokenProvider = new EmailTokenProvider UserModel (); _userManager.RegisterTokenProvider( Default , emailTokenProvider); } public async Task bool ConfirmEmail(string email, string code) { var start = DateTime.Now; _logger.LogTrace($ Potwierdzenie adresu e-mail {email} ); var stopwatch = new Stopwatch(); stopwatch.Start(); try 281 Poleć książkęKup książkę ASP.NET Core 2.0. Wprowadzenie { var user = await _userManager.FindByEmailAsync(email); if (user == null) return false; var result = await _userManager.ConfirmEmailAsync(user, code); return result.Succeeded; } catch (Exception ex) { _logger.LogError($ Nie mo(cid:285)na potwierdzi(cid:202) adresu e-mail {email} - {ex} ); return false; } finally { stopwatch.Stop(); _logger.LogTrace($ Potwierdzenie adresu e-mail u(cid:285)ytkownika uko(cid:241)czono w ci(cid:200)gu (cid:180){stopwatch.Elapsed} ); } } public async Task string GetEmailConfirmationCode(UserModel user) { return await _userManager.GenerateEmailConfirmationTokenAsync(user); } public async Task bool RegisterUser(UserModel userModel) { var start = DateTime.Now; _logger.LogTrace($ Rozpocz(cid:218)cie rejestracji u(cid:285)ytkownika {userModel.Email} - (cid:180){start} ); var stopwatch = new Stopwatch(); stopwatch.Start(); try { userModel.UserName = userModel.Email; var result = await _userManager.CreateAsync(userModel, userModel.Password); return result == IdentityResult.Success; } catch (Exception ex) { _logger.LogError($ Nie mo(cid:285)na zarejestrowa(cid:202) u(cid:285)ytkownika {userModel.Email} (cid:180)- {ex} ); return false; } finally { stopwatch.Stop(); 282 Poleć książkęKup książkę Rozdzia(cid:225) 9. • Zabezpieczanie aplikacji ASP.NET Core 2.0 _logger.LogTrace($ Rozpocz(cid:218)cie rejestracji u(cid:285)ytkownika {userModel.Email} (cid:180)zako(cid:241)czono o {DateTime.Now} - up(cid:239)yn(cid:218)(cid:239)o(y){stopwatch.Elapsed.TotalSeconds} (cid:180)sekund(y) ); } } public async Task UserModel GetUserByEmail(string email) { return await _userManager.FindByEmailAsync(email); } public async Task bool IsUserExisting(string email) { return (await _userManager.FindByEmailAsync(email)) != null; } public async Task IEnumerable UserModel GetTopUsers(int numberOfUsers) { return await _userManager.Users.OrderByDescending(x = x.Score).ToListAsync(); } public async Task UpdateUser(UserModel userModel) { await _userManager.UpdateAsync(userModel); } } Powiniene(cid:258) równie(cid:285) poprawi(cid:202) klas(cid:218) UserServiceTest, (cid:285)eby dzia(cid:239)a(cid:239)a z nowym konstrukto- rem. W tym celu musisz tak(cid:285)e utworzy(cid:202) atrap(cid:218) klasy UserManager i przekaza(cid:202) j(cid:200) do konstruk- tora. W chwili obecnej mo(cid:285)esz po prostu zakomentowa(cid:202) ten test i zaktualizowa(cid:202) go pó(cid:283)niej. Ale nie zapomnij tego zrobi(cid:202)! 7. Popraw metod(cid:218) EmailConfirmation klasy UserRegistrationController, u(cid:285)ywaj(cid:200)c do pobrania kodu potwierdzenia adresu e-mail dodanej wcze(cid:258)niej metody GetEmailConfirmationCode: var urlAction = new UrlActionContext { Action = ConfirmEmail , Controller = UserRegistration , Values = new { email, code = await _userService.GetEmailConfirmationCode(user) }, Protocol = Request.Scheme, Host = Request.Host.ToString() }; 8. Popraw metod(cid:218) ConfirmEmail klasy UserRegistrationController; w celu zako(cid:241)czenia potwierdzania adresu e-mail musi ona wywo(cid:239)ywa(cid:202) metod(cid:218) ConfirmEmail klasy UserService: 283 Poleć książkęKup książkę ASP.NET Core 2.0. Wprowadzenie [HttpGet] public async Task IActionResult ConfirmEmail(string email, string code) { var confirmed = await _userService.ConfirmEmail(email, code); if (!confirmed) return BadRequest(); return RedirectToAction( Index , Home ); } 9. Do folderu Models dodaj klas(cid:218) RoleModel; niech dziedziczy po klasie generycznej IdentityRole Guid , poniewa(cid:285) b(cid:218)dzie u(cid:285)ywana przez funkcje uwierzytelnienia frameworka Identity platformy ASP.NET Core 2.0: public class RoleModel : IdentityRole Guid { public RoleModel() { } public RoleModel(string roleName) : base(roleName) { } } 10. Popraw klas(cid:218) GameDbContext, dodaj(cid:200)c instancj(cid:218) DbSet z modelami ról: public DbSet RoleModel RoleModels { get; set; } 11. W klasie Startup zarejestruj us(cid:239)ug(cid:218) uwierzytelniania i us(cid:239)ug(cid:218) to(cid:285)samo(cid:258)ci z u(cid:285)yciem dodanej wcze(cid:258)niej klasy RoleModel: services.AddIdentity UserModel, RoleModel (options = { options.Password.RequiredLength = 1; options.Password.RequiredUniqueChars = 0; options.Password.RequireNonAlphanumeric = false; options.Password.RequireUppercase = false; options.SignIn.RequireConfirmedEmail = false; }).AddEntityFrameworkStores GameDbContext () .AddDefaultTokenProviders(); services.AddAuthentication(options = { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; }).AddCookie(); 284 Poleć książkęKup książkę Rozdzia(cid:225) 9. • Zabezpieczanie aplikacji ASP.NET Core 2.0 12. Zmie(cid:241) klas(cid:218) CommunicationMiddleware, usuwaj(cid:200)c z niej prywatn(cid:200) sk(cid:239)adow(cid:200) _userService i odpowiednio poprawiaj(cid:200)c konstruktor: public CommunicationMiddleware(RequestDelegate next) { _next = next; } 13. W klasie CommunicationMiddleware popraw obie metody ProcessEmailConfirmation; aby mog(cid:239)y wspó(cid:239)pracowa(cid:202) z frameworkiem Identity platformy ASP.NET Core 2.0, musz(cid:200) by(cid:202) asynchroniczne: private async Task ProcessEmailConfirmation(HttpContext context, WebSocket currentSocket, CancellationToken ct, string email) { var userService = context.RequestServices.GetRequiredService IUserService (); var user = await userService.GetUserByEmail(email); while (!ct.IsCancellationRequested !currentSocket.CloseStatus.HasValue user?.IsEmailConfirmed == false) { await SendStringAsync(currentSocket, WaitEmailConfirmation , ct); await Task.Delay(500); user = await userService.GetUserByEmail(email); } if (user.IsEmailConfirmed) { await SendStringAsync(currentSocket, OK , ct); } } private async Task ProcessEmailConfirmation(HttpContext context) { var userService = context.RequestServices.GetRequiredService IUserService (); var email = context.Request.Query[ email ]; UserModel user = await userService.GetUserByEmail(email); if (string.IsNullOrEmpty(email)) { await context.Response.WriteAsync( Nieprawid(cid:239)owe (cid:285)(cid:200)danie: (cid:180)Wymagany jest adres e-mail ); } else if ((await userService.GetUserByEmail(email)).IsEmailConfirmed) { await context.Response.WriteAsync( OK ); } } 285 Poleć książkęKup książkę ASP.NET Core 2.0. Wprowadzenie 14. W klasie GameInvitationService zmie(cid:241) konstruktor publiczny na statyczny. 15. Z klasy Startup usu(cid:241) nast(cid:218)puj(cid:200)c(cid:200) rejestracj(cid:218) instancji DbContextOptions; w nast(cid:218)pnym kroku zostanie zmieniona na inn(cid:200): var dbContextOptionsbuilder = new DbContextOptionsBuilder GameDbContext () .UseSqlServer(connectionString); services.AddSingleton(dbContextOptionsbuilder.Options); 16. Dodaj now(cid:200) rejestracj(cid:218) instancji DbContextOptions w klasie Startup: services.AddScoped(typeof(DbContextOptions GameDbContext ), (serviceProvider) = { return new DbContextOptionsBuilder GameDbContext () .UseSqlServer(connectionString).Options; }); 17. Na ko(cid:241)cu metody Configure klasy Startup zmie(cid:241) kod dokonuj(cid:200)cy migracji bazy danych: var provider = app.ApplicationServices; var scopeFactory = provider.GetRequiredService IServiceScopeFactory (); using (var scope = scopeFactory.CreateScope()) using (var context = scope.ServiceProvider.GetRequiredService GameDbContext ()) { context.Database.Migrate(); } 18. Zmie(cid:241) metod(cid:218) Index klasy GameInvitationController: ... var invitation = gameInvitationService.Add(gameInvitationModel).Result; return RedirectToAction( GameInvitationConfirmation , new { id = invitation.Id }); ... 19. Zmie(cid:241) metod(cid:218) ConfirmGameInvitation klasy GameInvitationController, dodaj(cid:200)c do istniej(cid:200)cej rejestracji u(cid:285)ytkownika dodatkowe pola: await _userService.RegisterUser(new UserModel { Email = gameInvitation.EmailTo, EmailConfirmationDate = DateTime.Now, EmailConfirmed = true, FirstName = , LastName = , Password = Azerty123! , UserName = gameInvitation.EmailTo }); 286 Poleć książkęKup książkę Rozdzia(cid:225) 9. • Zabezpieczanie aplikacji ASP.NET Core 2.0 Automatyczne tworzenie i rejestracja zaproszonego u(cid:285)ytkownika s(cid:200) tylko tymczasowym obej- (cid:258)ciem wprowadzonym po to, by upro(cid:258)ci(cid:202) przyk(cid:239)adow(cid:200) aplikacj(cid:218). W rzeczywistych warunkach nale(cid:285)y inaczej obs(cid:239)u(cid:285)y(cid:202) ten przypadek i zamieni(cid:202) tymczasowe obej(cid:258)cie na prawdziwe rozwi(cid:200)- zanie. 20. W klasie GameSessionService zmie(cid:241) metody CreateGameSession i AddTurn oraz ponownie wyodr(cid:218)bnij interfejs IGameSessionService: public async Task GameSessionModel CreateGameSession( Guid invitationId, UserModel invitedBy, UserModel invitedPlayer) { var session = new GameSessionModel { User1 = invitedBy, User2 = invitedPlayer, Id = invitationId, ActiveUser = invitedBy }; _sessions.Add(session); return session; } public async Task GameSessionModel AddTurn(Guid id, UserModel user, int x, int y) { List Models.TurnModel turns; var gameSession = _sessions.FirstOrDefault(session = session.Id == id); if (gameSession.Turns != null gameSession.Turns.Any()) turns = new List Models.TurnModel (gameSession.Turns); else turns = new List TurnModel (); turns.Add(new TurnModel { User = user, X = x, Y = y, IconNumber = user.Email == gameSession.User1?.Email ? 1 : 2 }); gameSession.Turns = turns; gameSession.TurnNumber = gameSession.TurnNumber + 1; if (gameSession.User1?.Email == user.Email) gameSession.ActiveUser = gameSession.User2; else gameSession.ActiveUser = gameSession.User1; gameSession.TurnFinished = true; _sessions = new ConcurrentBag GameSessionModel 287 Poleć książkęKup książkę ASP.NET Core 2.0. Wprowadzenie (_sessions.Where(u = u.Id != id)) { gameSession }; return gameSession; } 21. Zmie(cid:241) metod(cid:218) Index klasy GameSessionController: public async Task IActionResult Index(Guid id) { var session = await _gameSessionService.GetGameSession(id); var userService = HttpContext.RequestServices.GetService IUserService (); if (session == null) { var gameInvitationService = Request.HttpContext.RequestServices.GetService IGameInvitationService (); var invitation = await gameInvitationService.Get(id); var invitedPlayer = await userService.GetUserByEmail(invitation.EmailTo); var invitedBy = await userService.GetUserByEmail(invitation.InvitedBy); session = await _gameSessionService.CreateGameSession( invitation.Id, invitedBy, invitedPlayer); } return View(session); } 22. Popraw metod(cid:218) SetPosition klasy GameSessionController, przekazuj(cid:200)c w niej zamiast w(cid:239)a(cid:258)ciwo(cid:258)ci turn.User.Email obiekt klasy turn.User: gameSession = await _gameSessionService.AddTurn(gameSession.Id, turn.User, turn.X, turn.Y); 23. Zmie(cid:241) metod(cid:218) OnModelCreating klasy GameDbContext, dodaj(cid:200)c klucz obcy WinnerId: ... modelBuilder.Entity(typeof(GameSessionModel)) .HasOne(typeof(UserModel), Winner ) .WithMany() .HasForeignKey( WinnerId ).OnDelete(DeleteBehavior.Restrict); ... 24. Popraw metod(cid:218) GameInvitationConfirmation klasy GameInvitationController; aby mog(cid:239)a wspó(cid:239)pracowa(cid:202) z frameworkiem Identity platformy ASP.NET Core 2.0, musi by(cid:202) asynchroniczna: [HttpGet] public async Task IActionResult GameInvitationConfirmation( Guid id, [FromServices]IGameInvitationService 288 Poleć książkęKup książkę Rozdzia(cid:225) 9. • Zabezpieczanie aplikacji ASP.NET Core 2.0 gameInvitationService) { return await Task.Run(() = { var gameInvitation = gameInvitationService.Get(id).Result; return View(gameInvitation); }); } 1. Popraw metody Index i SetCulture klasy HomeController; aby mog(cid:239)y wspó(cid:239)pracowa(cid:202) z frameworkiem Identity platformy ASP.NET Core 2.0, musz(cid:200) by(cid:202) asynchroniczne: public async Task IActionResult Index() { return await Task.Run(() = { var culture = Request.HttpContext.Session.GetString( culture ); ViewBag.Language = culture; return View(); }); } public async Task IActionResult SetCulture(string culture) { return await Task.Run(() = { Request.HttpContext.Session.SetString( culture , culture); return RedirectToAction( Index ); }); } 1. Popraw metod(cid:218) Index klasy UserRegistrationController; aby mog(cid:239)a wspó(cid:239)pracowa(cid:202) z frameworkiem Identity platformy ASP.NET Core 2.0, musi by(cid:202) asynchroniczna: public async Task IActionResult Index() { return await Task.Run(() = { return View(); }); } 27. Otwórz konsol(cid:218) mened(cid:285)era pakietów i wykonaj polecenie Add-Migration IdentityDb. 28. Zaktualizuj baz(cid:218) danych, wykonuj(cid:200)c w konsoli mened(cid:285)era pakietów polecenie Update-Database. 29. Uruchom aplikacj(cid:218) i zarejestruj u(cid:285)ytkownika, a potem sprawd(cid:283), czy wszystko dzia(cid:239)a, jak powinno. Aby przej(cid:258)(cid:202) pomy(cid:258)lnie rejestracj(cid:218) u(cid:285)ytkownika, musisz teraz u(cid:285)y(cid:202) z(cid:239)o(cid:285)onego has(cid:239)a w stylu Azerty123!, poniewa(cid:285) zaimplementowa(cid:239)e(cid:258) funkcje wchodz(cid:200)ce w sk(cid:239)ad frameworka Identity platformy ASP.NET Core 2.0, które wymagaj(cid:200) z(cid:239)o(cid:285)onych hase(cid:239). 289 Poleć książkęKup książkę ASP.NET Core 2.0. Wprowadzenie Wprowadzanie podstawowego uwierzytelnienia za pomoc(cid:200) formularza Wspaniale! Zarejestrowa(cid:239)e(cid:258) oprogramowanie po(cid:258)rednicz(cid:200)ce uwierzytelniania i przygotowa(cid:239)e(cid:258) baz(cid:218) danych. Kolejnym krokiem b(cid:218)dzie implementacja w aplikacji Kó(cid:239)ko i krzy(cid:285)yk podstawowe- go uwierzytelniania. Poni(cid:285)szy przyk(cid:239)ad demonstruje, jak zmodyfikowa(cid:202) rejestracj(cid:218) u(cid:285)ytkowników oraz jak w celu ich uwierzytelniania doda(cid:202) prosty formularz logowania z polami nazwy u(cid:285)ytkownika oraz has(cid:239)a: 1. Do folderu Models dodaj klas(cid:218) LoginModel: public class LoginModel { [Required] public string UserName { get; set; } [Required] public string Password { get; set; } public string ReturnUrl { get; set; } } 2. Do folderu Views dodaj folder Account, a w nim plik o nazwie Login.cshtml, który b(cid:218)dzie zawiera(cid:239) widok logowania: @model TicTacToe.Models.LoginModel div class= container div id= loginbox style= margin-top:50px; class= mainbox col-md-6 col-md-offset-3 col-sm-8 col-sm-offset-2 div class= panel panel-info div class= panel-heading div class= panel-title Logowanie /div /div div style= padding-top:30px class= panel-body div style= display:none id= login-alert class= alert alert-danger col-sm-12 /div form id= loginform class= form-horizontal role= form asp-action= Login asp-controller= Account input type= hidden asp-for= ReturnUrl / div asp-validation-summary= ModelOnly class= text-danger /div div style= margin-bottom: 25px class= input-group span class= input-group-addon i class= glyphicon glyphicon-user /i /span input type= text class= form-control asp-for= UserName value= placeholder= nazwa u(cid:285)ytkownika (cid:180)lub adres e-mail /div div style= margin-bottom: 25px class= input-group span class= input-group-addon i class= glyphicon glyphicon-lock /i /span input type= password class= form-control 290 Poleć książkęKup książkę Rozdzia(cid:225) 9. • Zabezpieczanie aplikacji ASP.NET Core 2.0 asp-for= Password placeholder= has(cid:239)o /div div style= margin-top:10px class= form-group div class= col-sm-12 controls button type= submit id= btn-login href= # class= btn btn-success Zaloguj si(cid:218) /button /div /div div class= form-group div class= col-md-12 control div style= border-top: 1px solid#888; padding-top:15px; font-size:85 Nie masz konta? a asp-action= Index asp-controller= UserRegistration Za(cid:239)ó(cid:285) je tutaj /a /div /div /div /form /div /div /div /div 3. W klasie UserService dodaj prywatne pole SignInManager i zaktualizuj konstruktor: ... private SignInManager UserModel _signInManager; public UserService(ApplicationUserManager userManager, ILogger UserService logger, SignInManager UserModel signInManager) { ... _signInManager = signInManager; ... } ... 4. Do klasy UserService dodaj dwie metody o nazwach SignInUser i SignOutUser oraz zaktualizuj interfejs IUserService: public async Task SignInResult SignInUser( LoginModel loginModel, HttpContext httpContext) { var start = DateTime.Now; _logger.LogTrace($ logowanie u(cid:285)ytkownika {loginModel.UserName} ); var stopwatch = new Stopwatch(); stopwatch.Start(); try { var user = await _userManager.FindByNameAsync(loginModel.UserName); 291 Poleć książkęKup książkę ASP.NET Core 2.0. Wprowadzenie var isValid = await _signInManager.CheckPasswordSignInAsync(user, loginModel.Password, true); if (!isValid.Succeeded) { return SignInResult.Failed; } if (!await _userManager.IsEmailConfirmedAsync(user)) { return SignInResult.NotAllowed; } var identity = new ClaimsIdentity( CookieAuthenticationDefaults.AuthenticationScheme); identity.AddClaim(new Claim( ClaimTypes.Name, loginModel.UserName)); identity.AddClaim(new Claim( ClaimTypes.GivenName, user.FirstName)); identity.AddClaim(new Claim( ClaimTypes.Surname, user.LastName)); identity.AddClaim(new Claim( displayName , $ {user.FirstName} {user.LastName} )); if (!string.IsNullOrEmpty(user.PhoneNumber)) { identity.AddClaim(new Claim(ClaimTypes.HomePhone, user.PhoneNumber)); } identity.AddClaim(new Claim( Score , user.Score.ToString())); await httpContext.SignInAsync( CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity), new AuthenticationProperties { IsPersistent = false }); return isValid; } catch (Exception ex) { _logger.LogError($ nie mo(cid:285)na zalogowa(cid:202) u(cid:285)ytkownika {loginModel.UserName} (cid:180)- {ex} ); throw ex; } finally { stopwatch.Stop(); _logger.LogTrace($ logowanie u(cid:285)ytkownika {loginModel.UserName} uko(cid:241)czono (cid:180)w czasie {stopwatch.Elapsed} ); } } 292 Poleć książkęKup książkę Rozdzia(cid:225) 9. • Zabezpieczanie aplikacji ASP.NET Core 2.0 public async Task SignOutUser(HttpContext httpContext) { await _signInManager.SignOutAsync(); await httpContext.SignOutAsync(new AuthenticationProperties { IsPersistent = false }); return; } 5. Do folderu Controllers dodaj klas(cid:218) AccountController i zaimplementuj trzy nowe metody do obs(cid:239)ugi uwierzytelniania u(cid:285)ytkownika: public class AccountController : Controller { private IUserService _userService; public AccountController(IUserService userService) { _userService = userService; } public async Task IActionResult Login(string returnUrl) { return await Task.Run(() = { var loginModel = new LoginModel { ReturnUrl = returnUrl }; return View(loginModel); }); } [HttpPost] public async Task IActionResult Login(LoginModel loginModel) { if (ModelState.IsValid) { var result = await _userService.SignInUser(loginModel, HttpContext); if (result.Succeeded) { if (!string.IsNullOrEmpty(loginModel.ReturnUrl)) return Redirect(loginModel.ReturnUrl); else return RedirectToAction( Index , Home ); } else ModelState.AddModelError( , result.IsLockedOut ? U(cid:285)ytkownik jest zablokowany : U(cid:285)ytkownik nie ma prawa dost(cid:218)pu ); } return View(); } public IActionResult Logout() { _userService.SignOutUser(HttpContext).Wait(); HttpContext.Session.Clear(); 293 Poleć książkęKup książkę ASP.NET Core 2.0. Wprowadzenie return RedirectToAction( Index , Home ); } } 6. Zmie(cid:241) metod(cid:218) CheckGameSessionIsFinished klasy GameSessionController: [HttpGet( /restapi/v1/CheckGameSessionIsFinished/{sessionId} )] public async Task IActionResult CheckGameSessionIsFinished( Guid sessionId) { if (sessionId != Guid.Empty) { var session = await _gameSessionService.GetGameSession(sessionId); if (session != null) { if (session.Turns.Count() == 9) return Ok( Gra zako(cid:241)czy(cid:239)a si(cid:218) remisem. ); var userTurns = session.Turns.Where( x = x.User.Id == session.User1.Id).ToList(); var user1Won = CheckIfUserHasWon(session.User1?.Email, userTurns); if (user1Won) { return Ok($ {session.User1.Email} wygra(cid:239) gr(cid:218). ); } else { userTurns = session.Turns.Where( x = x.User.Id == session.User2.Id).ToList(); var user2Won = CheckIfUserHasWon(session.User2?.Email, userTurns); if (user2Won) return Ok($ {session.User2.Email} wygra(cid:239) gr(cid:218). ); else return Ok( ); } } else { return NotFound($ Nie mo(cid:285)na odnale(cid:283)(cid:202) rozgrywki {sessionId}. ); } } else { return BadRequest( Identyfikator SessionId jest pusty. ); } } 294 Poleć książkęKup książkę Rozdzia(cid:225) 9. • Zabezpieczanie aplikacji ASP.NET Core 2.0 7. Zmie(cid:241) blok kodu na pocz(cid:200)tku pliku Views/Shared/_Menu.cshtml: @using Microsoft.AspNetCore.Http; @{ var email = User?.Identity?.Name ?? Context.Session.GetString( email ); var displayName = User.Claims.FirstOrDefault( x = x.Type == displayName )?.Value ?? Context.Session.GetString( displayName ); } 8. Zmie(cid:241) plik Views/Shared/_Menu.cshtml, aby uwierzytelnionym u(cid:285)ytkownikom pokaza(cid:202) element nazwy wy(cid:258)wietlanej, a nieuwierzytelnionym element logowania; w tym celu zmie(cid:241) zawarto(cid:258)(cid:202) ostatniego znacznika li : li @if (!string.IsNullOrEmpty(email)) { Html.RenderPartial( _Account , new TicTacToe.Models.AccountModel { Email = email, DisplayName = displayName }); } else { a asp-area= asp-controller= Account asp-action= Login Logowanie /a } /li 9. Popraw plik Views/Shared/_Account.cshtml, zmieniaj(cid:200)c linki Wyloguj si(cid:218) i Zobacz szczegó(cid:239)y: a class= btn btn-danger btn-block asp-controller= Account asp-action= Logout asp-area= Wyloguj si(cid:218) /a a class= btn btn-default btn-block asp-action= Index asp-controller= Home asp-area= Account Zobacz szczegó(cid:239)y /a 10. Przejd(cid:283) do folderu Views\Shared\Components\GameSession i zmie(cid:241) plik default.cshtml, aby poprawi(cid:202) prezentacj(cid:218) wizualn(cid:200): @using Microsoft.AspNetCore.Http @model TicTacToe.Models.GameSessionModel @{ var email = Context.Session.GetString( email ); } div id= gameBoard table @for (int rows = 0; rows 3; rows++) { tr style= height:150px; @for (int columns = 0; columns 3; columns++) { td style= width:150px; border:1px solid #808080; text-align:center; vertical-align:middle id= @($ c_{rows}_{columns} ) @{ 295 Poleć książkęKup książkę ASP.NET Core 2.0. Wprowadzenie var position = Model.Turns?.FirstOrDefault( turn = turn.X == columns turn.Y == rows); if (position != null) { if (position.User == Model.User1) { i class= glyphicon glyphicon-unchecked /i } else { i class= glyphicon glyphicon-remove-circle /i } } else { a class= btn btn-default btn-SetPosition style= width:150px; min-height:150px; data-X= @columns data-Y= @rows nbsp; /a } } /td } /tr } /table /div div class= alert id= divAlertWaitTurn i class= glyphicon glyphicon-alert Prosz(cid:218) czeka(cid:202), a(cid:285) drugi u(cid:285)ytkownik sko(cid:241)czy kolejk(cid:218). /i /div 11. Uruchom aplikacj(cid:218), kliknij pozycj(cid:218) Zaloguj si(cid:218) w g(cid:239)ównym menu i zaloguj si(cid:218) na konto istniej(cid:200)cego u(cid:285)ytkownika (albo zarejestruj u(cid:285)ytkownika, je(cid:258)li tego wcze(cid:258)niej nie zrobi(cid:239)e(cid:258)): 296 Poleć książkęKup książkę Rozdzia(cid:225) 9. • Zabezpieczanie aplikacji ASP.NET Core 2.0 12. Kliknij przycisk Wyloguj si(cid:218). Powiniene(cid:258) zosta(cid:202) wylogowany i przekierowany z powrotem na stron(cid:218) g(cid:239)ówn(cid:200): Wprowadzanie uwierzytelniania za po(cid:258)rednictwem zewn(cid:218)trznego dostawcy W kolejnym punkcie zaprezentujemy uwierzytelnianie za po(cid:258)rednictwem zewn(cid:218)trznego do- stawcy, u(cid:285)ywaj(cid:200)c do tego serwisu Facebook. Oto przegl(cid:200)d przep(cid:239)ywu sterowania w takim wypadku: 1. U(cid:285)ytkownik klika specjalny przycisk logowania do zewn(cid:218)trznego dostawcy. 2. Odpowiedni kontroler otrzymuje (cid:285)(cid:200)danie wskazuj(cid:200)ce, który dostawca jest potrzebny, a nast(cid:218)pnie do tego dostawcy kierowane jest pytanie (ang. challenge). 3. Zewn(cid:218)trzny dostawca wysy(cid:239)a do aplikacji zwrotne (cid:285)(cid:200)danie HTTP (typu POST lub GET) z nazw(cid:200) dostawcy, kluczem oraz pewnymi o(cid:258)wiadczeniami u(cid:285)ytkownika. 4. Aplikacja sprawdza, czy te o(cid:258)wiadczenia pasuj(cid:200) do którego(cid:258) z wewn(cid:218)trznych u(cid:285)ytkowników. 5. Je(cid:258)li o(cid:258)wiadczenia nie pasuj(cid:200) do (cid:285)adnego u(cid:285)ytkownika wewn(cid:218)trznego, u(cid:285)ytkownik jest przekierowywany do odpowiedniego formularza rejestracji albo jest odrzucany. Etapy implementacji dla wszystkich zewn(cid:218)trznych dostawców, którzy wspieraj(cid:200) interfejs OWIN i framework Identity platformy ASP.NET Core 2.0, s(cid:200) takie same. Mo(cid:285)esz nawet stwo- rzy(cid:202) w(cid:239)asnego dostawc(cid:218) i zintegrowa(cid:202) go w ten sam sposób. Zaimplementujemy teraz uwierzytelnianie za po(cid:258)rednictwem zewn(cid:218)trznego dostawcy na przy- k(cid:239)adzie serwisu Facebook: 6. Zmie(cid:241) formularz logowania, dodaj(cid:200)c bezpo(cid:258)rednio po standardowym przycisku logowania przycisk Zaloguj si(cid:218) przez Facebook: a id= btn-fblogin asp-action= ExternalLogin asp-controller= Account asp-route-Provider= Facebook class= btn btn-primary Zaloguj si(cid:218) przez Facebook /a 297 Poleć książkęKup książkę ASP.NET Core 2.0. Wprowadzenie 13. Zmie(cid:241) klas(cid:218) UserService oraz interfejs IUserService, dodaj(cid:200)c trzy metody o nazwach GetExternalAuthenticationProperties, GetExternalLoginInfoAsync i ExternalLogin (cid:180)SignInAsync: public async Task AuthenticationProperties GetExternalAuthenticationProperties(string provider, string redirectUrl) { return await Task.FromResult( _signInManager.ConfigureExternalAuthenticationProperties( provider, redirectUrl)); } public async Task ExternalLoginInfo GetExternalLoginInfoAsync() { return await _signInManager.GetExternalLoginInfoAsync(); } public async Task SignInResult ExternalLoginSignInAsync( string loginProvider, string providerKey, bool isPersistent) { _logger.LogInformation($ Logowanie u(cid:285)ytkownika przez zewn(cid:218)trzny serwis {loginProvider} - {providerKey} ); return await _signInManager.ExternalLoginSignInAsync( loginProvider, providerKey, isPersistent); } 14. Zmie(cid:241) klas(cid:218) AccountController, dodaj(cid:200)c dwie metody o nazwach ExternalLogin i ExternalLoginCallBack: [AllowAnonymous] public async Task ActionResult ExternalLogin(string provider, string ReturnUrl) { var redirectUrl = Url.Action(nameof(ExternalLoginCallBack), Account , new { ReturnUrl = ReturnUrl }, Request.Scheme, Request.Host.ToString()); var properties = await _userService.GetExternalAuthenticationProperties( provider, redirectUrl); ViewBag.ReturnUrl = redirectUrl; return Challenge(properties, provider); } [AllowAnonymous] public async Task IActionResult ExternalLoginCallBack( string returnUrl, string remoteError = null) { if (remoteError != null) { ModelState.AddModelError(string.Empty, $ B(cid:239)(cid:200)d zewn(cid:218)trznego dostawcy: (cid:180){remoteError} ); ViewBag.ReturnUrl = returnUrl; 298 Poleć książkęKup książkę Rozdzia(cid:225) 9. • Zabezpieczanie aplikacji ASP.NET Core 2.0 return View( Login ); } var info = await _userService.GetExternalLoginInfoAsync(); if (info == null) { return RedirectToAction( Login , new { ReturnUrl = returnUrl }); } var result = await _userService.ExternalLoginSignInAsync( info.LoginProvider, info.ProviderKey, isPersistent: false); if (result.Succeeded) { if (!string.IsNullOrEmpty(returnUrl)) return Redirect(returnUrl); else return RedirectToAction( Index , Home ); } if (result.IsLockedOut) { return View( Lockout ); } else { return View( NotFound ); } } 1. W klasie Startup zarejestruj oprogramowanie po(cid:258)rednicz(cid:200)ce serwisu Facebook: services.AddAuthentication(options = { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; }).AddCookie().AddFacebook(facebook = { facebook.AppId = 123 ; facebook.AppSecret = 123 ; facebook.ClientId = 123 ; facebook.ClientSecret = 123 ; }); Zanim b(cid:218)dziesz móg(cid:239) uwierzytelnia(cid:202) logowania za pomoc(cid:200) serwisu Facebook, musisz zaktu- alizowa(cid:202) konfiguracj(cid:218) jego oprogramowania po(cid:258)rednicz(cid:200)cego oraz zarejestrowa(cid:202) aplikacj(cid:218) na portalu programistów serwisu Facebook. Wi(cid:218)cej informacji (w j(cid:218)zyku angielskim) dost(cid:218)pnych jest na stronie http://developer.facebook.com. 299 Poleć książkęKup książkę ASP.NET Core 2.0. Wprowadzenie 16. Uruchom aplikacj(cid:218), kliknij przycisk Zaloguj si(cid:218) przez Facebook, wprowad(cid:283) swoje dane uwierzytelniaj(cid:200)ce do tego serwisu i sprawd(cid:283), czy wszystko dzia(cid:239)a tak, jak powinno: Praca z uwierzytelnianiem dwusk(cid:239)adnikowym Standardowe mechanizmy bezpiecze(cid:241)stwa, które widzia(cid:239)e(cid:258) wcze(cid:258)niej, wymagaj(cid:200) tylko prostej nazwy u(cid:285)ytkownika i has(cid:239)a, co w znacznym stopniu u(cid:239)atwia cyberprzest(cid:218)pcom uzyskanie dost(cid:218)pu do poufnych informacji, w tym szczegó(cid:239)owych danych osobistych i finansowych, w drodze z(cid:239)a- mania has(cid:239)a albo przej(cid:218)cia danych uwierzytelniaj(cid:200)cych u(cid:285)ytkownika [za pomoc(cid:200) wiadomo(cid:258)ci e-mail, szperania po sieci (ang. network sniffing) itp.]. Te dane bywaj(cid:200) potem u(cid:285)ywane do po- pe(cid:239)niania oszustw internetowych i kradzie(cid:285)y to(cid:285)samo(cid:258)ci. Uwierzytelnianie dwusk(cid:239)adnikowe wprowadza dodatkowy poziom zabezpiecze(cid:241), poniewa(cid:285) wy- maga nie tylko nazwy u(cid:285)ytkownika i has(cid:239)a, ale tak(cid:285)e kodu zabezpieczaj(cid:200)cego (wygenerowanego przez fizyczne urz(cid:200)dzenie, program itd.), który mo(cid:285)e poda(cid:202) jedynie u(cid:285)ytkownik. To bardzo utrudnia dost(cid:218)p potencjalnym intruzom i zabezpiecza przed kradzie(cid:285)(cid:200) to(cid:285)samo(cid:258)ci i danych. Wszystkie wi(cid:218)ksze strony internetowe zapewniaj(cid:200) opcj(cid:218) uwierzytelniania dwusk(cid:239)adnikowego, dodajmy wi(cid:218)c j(cid:200) równie(cid:285) do aplikacji Kó(cid:239)ko i krzy(cid:285)yk: 1. Dodaj model TwoFactorCodeModel do folderu Models: public class TwoFactorCodeModel { [Key] public long Id { get; set; } public Guid UserId { get; set; } [ForeignKey( UserId )] public UserModel User { get; set; } 300 Poleć książkęKup książkę Rozdzia(cid:225) 9. • Zabezpieczanie aplikacji ASP.NET Core 2.0 public string TokenProvider { get; set; } public string TokenCode { get; set; } } 2. Dodaj model TwoFactorEmailModel do folderu Models: public class TwoFactorEmailModel { public string DisplayName { get; set; } public string Email { get; set; } public string ActionUrl { get; set; } } 1. Zarejestruj model TwoFactorCodeModel w kontek(cid:258)cie bazy GameDbContext, dodaj(cid:200)c instancj(cid:218) odpowiedniego typu DbSet: public DbSet TwoFactorCodeModel TwoFactorCodeModels { get; set; } 4. Otwórz konsol(cid:218) mened(cid:285)era pakietów NuGet i wykonaj polecenie Add-Migration AddTwoFactorCode, a potem zaktualizuj baz(cid:218) danych poleceniem Update-Database. 5. Do klasy ApplicationUserManager dodaj trzy metody o nazwach SetTwoFactorEnabledAsync, GenerateTwoFactorTokenAsync i VerifyTwoFactorTokenAsync: public override async Task IdentityResult SetTwoFactorEnabledAsync(UserModel user, bool enabled) { try { using (var db = new GameDbContext(_dbContextOptions)) { var current = await db.UserModels.FindAsync(user.Id); current.TwoFactorEnabled = enabled; await db.SaveChangesAsync(); return IdentityResult.Success; } } catch (Exception ex) { return IdentityResult.Failed(new IdentityError { Description = ex.ToString() }); } } public override async Task string GenerateTwoFactorTokenAsync(UserModel user, string tokenProvider) { using (var dbContext = new GameDbContext(_dbContextOptions)) { var emailTokenProvider = new EmailTokenProvider UserModel (); var token = await emailTokenProvider.GenerateAsync( TwoFactor , this, user); dbContext.TwoFactorCodeModels.Add(new TwoFactorCodeModel { 301 Poleć książkęKup książkę ASP.NET Core 2.0. Wprowadzenie TokenCode = token, TokenProvider = tokenProvider, UserId = user.Id }); if (dbContext.ChangeTracker.HasChanges()) await dbContext.SaveChangesAsync(); return token; } } public override async Task bool VerifyTwoFactorTokenAsync(UserModel user, string tokenProvider, string token) { using (var dbContext = new GameDbContext(_dbContextOptions)) { return await dbContext.TwoFactorCodeModels.AnyAsync( x = x.TokenProvider == tokenProvider x.TokenCode == token x.UserId == user.Id); } } 1. Przejd(cid:283) do folderu Areas/Account/Views/Home i zmie(cid:241) domy(cid:258)lny widok: @model TicTacToe.Models.UserModel @using Microsoft.AspNetCore.Identity @inject UserManager TicTacToe.Models.UserModel UserManager @{ var isTwoFactor = UserManager.GetTwoFactorEnabledAsync(Model).Result; ViewData[ Title ] = Indeks ; Layout = ~/Views/Shared/_Layout.cshtml ; } h3 Szczegó(cid:239)y konta /h3 div class= container div class= row div class= col-xs-12 col-sm-6 col-md-6 div class= well well-sm div class= row div class= col-sm-6 col-md-4 Gravatar email= @Model.Email /Gravatar /div div class= col-sm-6 col-md-8 h4 @($ {Model.FirstName} {Model.LastName} ) /h4 p i class= glyphicon glyphicon-envelope /i nbsp; a href= mailto:@Model.Email @Model.Email /a /p p i class= glyphicon glyphicon-calendar 302 Poleć książkęKup książkę Rozdzia(cid:225) 9. • Zabezpieczanie aplikacji ASP.NET Core 2.0 /i nbsp;@Model.EmailConfirmationDate /p p i class= glyphicon glyphicon-star /i nbsp;@Model.Score /p p i class= glyphicon glyphicon-check /i text Uwierzytelnianie dwusk(cid:239)adnikowe nbsp; /text @if (Model.TwoFactorEnabled) { a asp-action= DisableTwoFactor Wy(cid:239)(cid:200)cz /a } else { a asp-action= EnableTwoFactor W(cid:239)(cid:200)cz /a } /p /div /div /div /div /div /div 7. Do folderu Areas/Account/Views dodaj plik _ViewImports.cshtml: @using TicTacToe @using Microsoft.AspNetCore.Mvc.Localization @inject IViewLocalizer Localizer @addTagHelper *, TicTacToe @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 8. Zmie(cid:241) klas(cid:218) UserService i interfejs IUserService, dodaj(cid:200)c dwie metody o nazwach EnableTwoFactor i GetTwoFactorCode: public async Task IdentityResult EnableTwoFactor(string name, bool enabled) { try { var user = await _userManager.FindByEmailAsync(name); user.TwoFactorEnabled = true; await _userManager.SetTwoFactorEnabledAsync(user, enabled); return IdentityResult.Success; } catch (Exception ex) { throw; } } public async Task string GetTwoFactorCode(string userName, string tokenProvider) 303 Poleć książkęKup książkę ASP.NET Core 2.0. Wprowadzenie { var user = await GetUserByEmail(userName); return await _userManager.GenerateTwoFactorTokenAsync(user, tokenProvider); } 9. Zmie(cid:241) metod(cid:218) SignInUser klasy UserService tak, by obs(cid:239)ugiwa(cid:239)a uwierzytelnianie dwusk(cid:239)adnikowe, je(cid:258)li jest w(cid:239)(cid:200)czone: public async Task SignInResult SignInUser(LoginModel loginModel, HttpContext httpContext) { var start = DateTime.Now; _logger.LogTrace($ Logowanie u(cid:285)ytkownika {loginModel.UserName} ); var stopwatch = new Stopwatch(); stopwatch.Start(); try { var user = await _userManager.FindByNameAsync(loginModel.UserName); var isValid = await _signInManager.CheckPasswordSignInAsync(user, loginModel.Password, true); if (!isValid.Succeeded) { return SignInResult.Failed; } if (!await _userManager.IsEmailConfirmedAsync(user)) { return SignInResult.NotAllowed; } if (await _userManager.GetTwoFactorEnabledAsync(user)) { return SignInResult.TwoFactorRequired; } var identity = new ClaimsIdentity( CookieAuthenticationDefaults.AuthenticationScheme); identity.AddClaim(new Claim(ClaimTypes.Name, loginModel.UserName)); identity.AddClaim(new Claim(ClaimTypes.GivenName, user.FirstName)); identity.AddClaim(new Claim(ClaimTypes.Surname, user.LastName)); identity.AddClaim(new Claim( displayName , $ {user.FirstName} {user.LastName} )); if (!string.IsNullOrEmpty(user.PhoneNumber)) { identity.AddClaim(new Claim(ClaimTypes.HomePhone, user.PhoneNumber)); } identity.AddClaim(new Claim( Score , user.Score.ToString())); await httpContext.SignInAsync( CookieAuthenticationDefaults.AuthenticationScheme, 304 Poleć książkęKup książkę Rozdzia(cid:225) 9. • Zabezpieczanie aplikacji ASP.NET Core 2.0 new ClaimsPrincipal(identity), new AuthenticationProperties { IsPersistent = false }); return isValid; } catch (Exception ex) { _logger.LogError($ Nie mo(cid:285)na zalogowa(cid:202) u(cid:285)ytkownika {loginModel.UserName} (cid:180)- {ex} ); throw ex; } finally { stopwatch.Stop(); _logger.LogTrace($ Logowanie u(cid:285)ytkownika {loginModel.UserName} uko(cid:241)czono (cid:180)w czasie {stopwatch.Elapsed} ); } } 10. Przejd(cid:283) do folderu Areas/Account/Controllers i zmie(cid:241) klas(cid:218) HomeController. Popraw jej metod(cid:218) Index i dodaj dwie nowe o nazwach EnableTwoFactor i DisableTwoFactor: [Authorize] public async Task IActionResult Index() { var user = await _userService.GetUserByEmail(User.Identity.Name); return View(user); } [Authorize] public IActionResult EnableTwoFactor() { _userService.EnableTwoFactor(User.Identity.Name, true); return RedirectToAction( Index ); } [Authorize] public IActionResult DisableTwoFactor() { _userService.EnableTwoFactor(User.Identity.Name, false); return RedirectToAction( Index ); } Atrybut [Authorize] obja(cid:258)nimy w dalszej cz(cid:218)(cid:258)ci rozdzia(cid:239)u. U(cid:285)ywa si(cid:218) go do wprowadzenia ogranicze(cid:241) dost(cid:218)pu do zasobów. 11. Do folderu Models dodaj klas(cid:218) ValidateTwoFactorModel: public class ValidateTwoFactorModel { public string UserName { get; set; } public string Code { get; set; } } 305 Poleć książkęKup książkę ASP.NET Core 2.0. Wprowadzenie 12. Do klasy AccountController dodaj metod(cid:218) SendEmailTwoFactor: private async Task SendEmailTwoFactor(string UserName) { var user = await _userService.GetUserByEmail(UserName); var urlAction = new UrlActionContext { Action = ValidateTwoFactor , Controller = Account , Values = new { email = UserName, code = await _userService.GetTwoFactorCode( user.UserName, Email ) }, Protocol = Request.Scheme, Host = Request.Host.ToString() }; var TwoFactorEmailModel = new TwoFactorEmailModel { DisplayName = $ {user.FirstName} {user.LastName} , Email = UserName, ActionUrl = Url.Action(urlAction) }; var emailRenderService = HttpContext.RequestServices.GetService IEmailTemplateRenderService (); var emailService = HttpContext.RequestServices.GetService IEmailService (); var message = await emailRenderService.RenderTemplate( EmailTemplates/TwoFactorEmail , TwoFactorEmailModel, Request.Host.ToString()); try { emailService.SendEmail(UserName, Kod zabezpieczaj(cid:200)cy aplikacji Kó(cid:239)ko (cid:180)i krzy(cid:285)yk , message).Wait(); } catch { } } Aby wywo(cid:239)a(cid:202) metod(cid:218) RequestServices.GetService T ();, tak jak w poprzednich przyk(cid:239)adach, nale(cid:285)y doda(cid:202) instrukcj(cid:218) using Microsoft.Extensions.DependencyInjection;. 13. Zmie(cid:241) metod(cid:218) Login klasy AccountController: [HttpPost] public async Task IActionResult Login(LoginModel loginModel) { if (ModelState.IsValid) 306 Poleć książkęKup książkę Rozdzia(cid:225) 9. • Zabezpieczanie aplikacji ASP.NET Core 2.0 { var result = await _userService.SignInUser(loginModel, HttpContext); if (result.Succeeded) { if (!string.IsNullOrEmpty(loginModel.ReturnUrl)) return Redirect(loginModel.ReturnUrl); else return RedirectToAction( Index , Home ); } else if (result.RequiresTwoFactor) { await SendEmailTwoFactor(loginModel.UserName); return RedirectToAction( ValidateTwoFactor ); } else ModelState.AddModelError( , result.IsLockedOut ? U(cid:285)ytkownik jest (cid:180)zablokowany : U(cid:285)ytkownik nie jest upowa(cid:285)niony ); } return View(); } 14. Do folderu Views/Account dodaj widok o nazwie ValidateTwoFactor: @model TicTacToe.Models.ValidateTwoFactorModel @{ ViewData[ Title ] = Weryfikacja dwusk(cid:239)adnikowa ; Layout = ~/Views/Shared/_Layout.cshtml ; } div class= container div id= loginbox style= margin-top:50px; class= mainbox col-md-6 col-md-offset-3 col-sm-8 col-sm-offset-2 div class= panel panel-info div class= panel-heading div class= panel-title Weryfikacja kodu zabezpieczaj(cid:200)cego /div /div div style= padding-top:30px class= panel-body div class= text-center form asp-controller= Account asp-action= ValidateTwoFactor method= post div asp-validation-summary= All /div div style= margin-bottom: 25px class= input-group span class= input-group-addon i class= glyphicon glyphicon-envelope color-blue /i /span input id= email asp-for= UserName placeholder= adres e-mail class= form-control type= email /div div style= margin-bottom: 25px class= input-group span class= input-group-addon i class= glyphicon glyphicon-lock 307 Poleć książkęKup książkę ASP.NET Core 2.0. Wprowadzenie color-blue /i /span input id= Code asp-for= Code placeholder= Wprowad(cid:283) kod class= form-control /div div style= margin-bottom: 25px class= input-group input name= submit class= btn btn-lg btn-primary btn-block value= Zweryfikuj kod type= submit /div /form /div /div /div /div /div 15. Do folderu Views/EmailTemplates dodaj widok o nazwie TwoFactorEmail: @model TicTacToe.Models.TwoFactorEmailModel @{ ViewData[ Title ] = Widok ; Layout = _LayoutEmail ; } h1 Witaj, @Model.DisplayName /h1 Chcesz otrzyma(cid:202) kod zabezpieczaj(cid:200)cy? Aby kontynuowa(cid:202), kliknij a href= @Model.ActionUrl tutaj /a . 16. Zmie(cid:241) klas(cid:218) UserService i interfejs IUserService, dodaj(cid:200)c metod(cid:218) ValidateTwoFactor: public async Task bool ValidateTwoFactor(string userName, string tokenProvider, string token, HttpContext httpContext) { var user = await GetUserByEmail(userName); if (await _userManager.VerifyTwoFactorTokenAsync(user, tokenProvider, token)) { var identity =
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

ASP.NET Core 2.0. Wprowadzenie
Autor:
,

Opinie na temat publikacji:


Inne popularne pozycje z tej kategorii:


Czytaj również:


Prowadzisz stronę lub blog? Wstaw link do fragmentu tej książki i współpracuj z Cyfroteką: