Stan programu Angular dla wielu użytkowników

0

Hej. Właśnie siedzę nad małym próbnym projektem. Chcę w nim wypróbować różne podejścia w Angular + ASP.NET Core. Projekt zakłada, że 2 osoby będą mogły zagrać ze sobą w kółko i krzyżyk, dla przykładu.

Zastanawiam się jak obaj gracze będą mogli uzyskać i mieć dostęp do stanu gry? Chcę zaznaczyć, że komunikacja między graczami ma się odbywać przy użyciu SignalR. Choć przyznaję, że jest to dla mnie nowe i nie mam jeszcze pewności czy wybór jest dobry, choć na chwilę obecną taki się wydaje.

Wracając do tematu, zakładając, że obaj gracze będą mogli prowadzić między sobą autoryzowaną komunikację, w każdej swojej rundzie każdy z nich de facto swoim kliknięciem zaktualizuje stan gry, czyli m.in. stan tablicy do gry w kółko i krzyżyk, każdego jej pola, wyniku itd.

Na chwilę obecną jedyne rozwiązanie jakie przychodzi mi do głowy to:

  • na samym początku utworzenie w TS obiektu stanu gry,
  • aktualizowanie u obu graczy obiektu stanu gry przy każdym kliknięciu na planszy przez jednego z graczy
  • odczyt i zapis przez obu graczy obiektu stanu gry do/z localStorage.

Czy to podejście jest poprawne? Czy muszę się liczyć z jakimiś trudnościami/zagrożeniami, w tym security? Czy znacie jakieś lepsze rozwiązania?

1

LocalStorage nie jest "przypisany do użytkownika" w takim sensie, że jest on stricte związany z przeglądarką, więc w chwili gdy zalogujesz się w innej przeglądarce / na innym komputerze i tracisz dane. To, gdzie po stronie frontu sobie to zapiszesz, to jest mało istotne gdzie sobie to zapiszesz: czy w Local/Session storage, komponencie, serwisie czy jakiejś libce do przechowywania stanu. Nie wiem czym jest SignalR, ale z tego co na szybko przeczytałem korzysta z WebSocketów (popraw mnie jeśli się mylę). Imo, gdzieś na serwerze musiałbyś przechowywać stan aktualnej gry. Trudności, zagrożenia? Musiałbyś pamiętać żeby localstorage czyścić wtedy kiedy będzie trzeba. Zależy też w sumie jak masz zrobiony mechanizm logowania i np. gdzie przechowujesz JWT.

0
Aisekai napisał(a):

LocalStorage nie jest "przypisany do użytkownika" w takim sensie, że jest on stricte związany z przeglądarką, więc w chwili gdy zalogujesz się w innej przeglądarce / na innym komputerze i tracisz dane.

Myślałem o tym, nie mam jeszcze gotowego rozwiązania, jedynie mam "wizję" przekazania (jakoś) obiektu stanu gry/programu do użytkownika który dołączy do rozpoczętej/utworzonej rozgrywki. Jak, tego jeszcze nie wiem, ale się dowiem :)

Aisekai napisał(a):

Musiałbyś pamiętać żeby localstorage czyścić wtedy kiedy będzie trzeba. Zależy też w sumie jak masz zrobiony mechanizm logowania i np. gdzie przechowujesz JWT.

JTW też jest sprawdzany na serwerze przy niektórych requestach. Dane użytkownika wysyłane z requestem, w tym token, są przechowywane w localstorage.

1

Model gry (klasę/klasy) sam musisz stworzyć, bo nie wiem co w nim jeszcze będziesz potrzebował. Natomiast pobrać aktualny stan, to zwyczajnie Http requestem, natomiast już komunikację między graczami - to już musiałbyś WebSockety dołączyć (prawdopodobnie właśnie to dostarcza Ci SignalR).

JWT nie przechowuj w LocalStorage, bo do niego masz bezpośredni dostęp gdziekolwiek z JSa. JWT przechowuj gdzieś w pamięci (jakiejś zmiennej w klasie), w Cookie przechowaj refresh token, na podstawie którego będziesz mógł dostać JWT. Oczywiście do tego Cookie nie powinieneś mieć dostępu z JSa, więc musi być HttpOnly. Co za tym idzie, za każdym razem, przed załadowaniem aplikacji musiałbyś wysłać requesta do serwera żeby dostać JWT (obsłużenie odświeżania strony i utraty JWT). W Angularze do tego masz providera APP_INITIALIZER, ewentualnie jakoś wyciągnąć wszystkie Route'y i na bazowym dać AuthGuarda który byłby odpalany tylko raz i wyciągałby z serwera JWT.

https://dev.to/gkoniaris/how-to-securely-store-jwt-tokens-51cf
https://medium.com/@ryanchenkie_40935/react-authentication-how-to-store-jwt-in-a-cookie-346519310e81

0
Aisekai napisał(a):

Natomiast pobrać aktualny stan, to zwyczajnie Http requestem, natomiast już komunikację między graczami - to już musiałbyś WebSockety dołączyć (prawdopodobnie właśnie to dostarcza Ci SignalR).

Teraz się zastanawiam, jeśli do pobrania obiektu typu stanu gry potrzebuję HTTP, to gdzie go przechowywać? Na serwerze? Np w jego pamięci? Nie da sie go przerzucić z przeglądarki do przeglądarki (localStorage) przy użyciu WebSocket?

1

Raczej musiałbyś to na serwerze przechowywać (ewentualnie próbować jakoś zrobić p2p, ale tego nigdy nie robiłem). Według mnie i tak musiałbyś mieć jakiś backend za to wszystko odpowiedzialny. Gdzie przechowasz dane odnośnie gry po stronie frontendu (localstorage, sessionstorage, pamięć, indexeddb itd) to już zależy od Ciebie, tak samo po stronie backendu (w bazie danych, scache'owane w pamięci itd). "Główny" obiekt stanu gry i tak musiałbyś przechować gdzieś po stronie backendu.

0

Okazuje się, że SignalR się świetnie nadaje do przekazywania customowego obiektu z klienta do klienta, przez węzeł na serwerze. Myślę, żeby obiekt stanu przechowywać w localStorage i aktualizować u wszystkich nasłuchujących klientów przy użyciu SignalR. Pozostaje mi ogarnięcie konfiguracji autentykacji JWT dla SignalR, na szczęście jest to też możliwe, ale to będzie już oddzielny rozdział ;p

1 użytkowników online, w tym zalogowanych: 0, gości: 1