VS C# .net core WPF EntityFramework MySQL minta

Fórumok

Üdv,

A $subj-hez keresek minta kódot (1-2 táblával). Nem találtam igazán jó példát.

Van valakinek ilyen?

Hozzászólások

Ez oké.

Olyat keresek, ami bemutatja milyen módon érdemes WPF alkalmazásban adatbázist kezelni. (Konzolon, web megvan)

Pl. egy tábla elegáns karbantartása (külső kulcsokkal is). A DBContext-et formonként külön érdemes kezelni? ...stb.

 

Ezt nézegetem most (bár ez .net framework 4.x + winforms):

https://github.com/nyuuuukie/client-server-app

Nem erre gondoltam, sorry.

Szoval az a kerdes, hogy a user sajat MySQL accounttal rendelkezik-e. Ha nem, azaz az alkalmazas minden peldanya ugyanazzal a user/pass parossal authentikal az adatbazis fele, akkor egyaltalan ne legyen DbContext a WPF appban, hanem legyen egy API valahol, ami a mogottes adatbazis alapjan kommunikal az appal. 

Bar nyilvan elofordul, hogy tenyleg minden end usernek van DB accountja, de ez annyira eletszerutlen, hogy tizen-par ev .NET fejelsztes utan is oszinten, fogalmam sincs, mi a best practice arra, hogy WPF appban EF context legyen. Ha nagyon gondolkodnom kene (pl. egy sqlite fajlt kell buzeralni lokalisan), akkor esetleg dependency injectionnel odaadni a DbContextet a formnak?

Szerintem nem túl elrugaszkodott dolog egy DESKTOP-os alkalmazásnál feltételezni, hogy a userek meg vannak különböztetve adatbázis oldalon is.

Mysql-t nem tudom, de mssql-nél alap az SSPI, azaz a domain accountjával, connection stringben tárolt jelszó nélkül authentikál az adatbázis felé és a probléma nem is értelmezhető.

De, ha api-t teszel a desktop alkalmazás és az adatbázis közé, ott hogy authentikálja magát a user az api felé és mindezt hol tárolja az alkalmazás? Az nem ugyanaz a progléma?

Ha nem tárolja, mert bekéri a nevet-jelszót, azt pont ugyanúgy bekérheti az adatbázis kapcsolathoz is.

OK, de továbbra sem értem, hogy ha a hülye DB nem képes mondjuk kerberoson authentikálni a bejelentkezett usert és ezért connectionstring-be kell letárolni a jelszót, azon hogy segit, ha kivesszük az alkalmazásból a közvetlen db elérést és helyette egy api-t hivogat.

Ott is le kell tárolni egy jelszót, csak nem a DB-hez, hanem az api-hoz.

A jó megoldásról fogalmam sincs. Amit eddig láttam már:

1. lokális alkalmazásnál: a) nem foglalkozik ezzel b) generál egy usert és jelszót a db-hez, amit eltárol

2. távoli megoldásnál API réteg, ami token alapon authentikál ezzel állapotot adva a RestAPI-hoz :)  pl: https://jwt.io/

3. távoli db használata (leginkább ügyviteli rendszerek) itt a szerver (db?) kapcsolathoz be kell állítani pár adatot (ip, user, pass)

Nem teljesen ertem a kerdest. Ha API-t hasznalsz, akkor nincs secret, amit bele kell egetni csomagba. A user authentikal valahogy az appban, kap egy tokent, es azzal intezheti a dolgait API-n keresztul. V.o.: van egy univerzalis credential a faszaAppom.msi-ban, amivel barki hozza tud ferni az adatokhoz.

Ha a DB tud userenkent sajat accounttal authentikalni, akkor nincs ilyen problema, ezert kerdeztem azt rogton a legelejen, hogy tud-e ilyet.

Ott is le kell tárolni egy jelszót, csak nem a DB-hez, hanem az api-hoz.

Dehogy kell, pont ez a lenyeg. :)

Én a választ nem értem... :)

Ha az api-hoz is be kell kérni a user-pass-t, akkor ez továbbra is értelmetlen. Miért tudják ott kezelni a usereket, ha az adatbázisban nem? Ennyit azért a mysql is tud.

Vagy bekérünk nevet jelszót a program felületén és akkor nem kell letárolni kliens oldalon jelszót, se api, se közvetlen adatbázis elérés esetén, vagy nem kérünk be jelszót és itt ketté válik: normális adatbáziskezelő tud authentikálni jelszó nélkül, pl kerberoson, vagy hülye adatbáziskezelő esetén le kell tárolni, akár api, akár közvetlen elérés.

A db a legérttékesebb, mert abban van az adat. Ha az a kérdés, hogy veri-e bármelyik másik auth megoldás azt, ami bele van építve, arra vsz nem a válasz, azaz látszólag igazad van. Viszont ha eléteszel egy bármilyen leválasztó elemet, akkor egy támadónak már 2 különböző technológián, 2 különböző authentikáción, 2 különböző szintű hálózati védelmen kell átjutni, ami nem 2x nehezebb, hanem sokszor. Minden rétegnek magát kell védeni, és csak a szükséges és elégséges jogokat és tartalmakat szolgáltatni egy adott irányban. Már csak azért is, mert cloud vagy sdn esetén egy véletlen benézett sor elég, hogy valami védtelenül kikerüljön az internetre. Legalább legyen olyan a design, hogy ehhez 2 sort kelljen célzottan elcseszni.

"Viszont ha eléteszel egy bármilyen leválasztó elemet, akkor egy támadónak már 2 különböző technológián, 2 különböző authentikáción, 2 különböző szintű hálózati védelmen kell átjutni, ami nem 2x nehezebb, hanem sokszor. "

Ennek a matematikája nekem nem jön ki. Ha a db-hez full hozzáfér az API, akkor miért is? Ha arra gondolsz, hogy az API stabil és szűkebb hozzáférést ad, mint egy fullos db hozzáférés, akkor igazad van. Már csak az a kérdés ekkor miért egy fullos db hozzáféréssel hasonlítod össze?

"Ha a db-hez full hozzáfér az API" - mert ennek nem kéne igaznak lennie. Persze ha csinálsz egy full CRUD API-t god joggal, akkor annak pont semmi értelme secu szempontból (más szempontból lehet, de az most irreleváns).

Normál esetben ennek így kéne kinézni:

  1. Kliens hív 443-at, amit egy határvédelmi eszköz végződtet. Mivel ismert az API tartalma, így lehet szűrni, hogy csak a protokollnak megfelelő dolgot a megengedett értékkészlettel hívja. Ha ezen nem megy át, az alkalmazásszerverig el sem jut. Ha nincs WAF, akkor ezt a validációt az alkalmazásszerveren kell megtenni (ott amúgy is illik, de azért érdemes előtte is megfogni, mert akkor nem a kiszolgáló komponenst terheli egy próbálkozó fals forgalom, plusz azt veri szemmel a SoC, nekik könnyebb WAF logot olvasni mint a fejlesztő által kreált alkalmazás logot.
  2. Tegyük fel az előző pontot valahogy megugrotta a hacker barátunk, akkor bent ül egy alaklmazás szerveren, ahonnan alapesetben nem kezdeményezhet forgalmat internet felé, csak és kizárólag a DB felé, optimális esetben szintén protokollszűrt módon, ezért marha nehezen jut hozzá a kedvenc szerszámaihoz
  3. Tegyük fel, valahogy ezt is megoldotta, és az alkalmazás szerveren már tudott privilégium szintet emelni vagy netán root shell-hez jutni, és így megszerezte a connection string-et
  4. Ekkor egy korlátozott (!) user-rel már hozzáfér a DB-hez, amiben csak és kizárólag az alkalmazásnak feltétlen szükséges dolgokat éri el. Legyen mindent is tudó alkalmazás, azaz mindent tud írni és olvasni. Ekkor el tudja lopni az adatokat, a jelen állapotot el is tudja rontani, de nem tud hozzáférni a WAL-hoz/mentéshez/replikához, így a működés hamar helyreállítható.

Tehát "csak" adatlopásig jut, azt is baromi nehezen, ha elrontott valamit, hamar helyreállítható, kivéve ha az alkalmazásszerver mellett a db is épp tele van ismert kritikus hibákkal, de az meg már az üzemeltetés trehányságára utal, mert annak, hogy két független komponensben egyszerre jelenik meg kritikus zero day, arra extrém pici az esély, legalábbis sokkal kisebb, minthogy évek óta nem patch-elték egyiket sem. 

Ráadásul ha az alkalmazásszerver horizontálisan skálázott, állapotmentes, akár "serverless", akkor pláne baromi nehéz dolga van a támadónak, mert minden próbálkozása random példányokon végződik, így nehezen tud lépésről lépésre haladni, mert a már recsegő példány helyett kap újat.

Ha simán csak kint van a DB a neten, akkor az egyetlen lépés, hisz kliens oldalon ott van a hozzáférés, és a full technikai infó a DB típusáról, verziójáról stb. Azaz onnantól csak várni kell a biztonsági híreket, és ha az adott db verzióban megjelenik egy komolyabb hiba, abban a pillanatban mindenestül a támadóé. 

Értem. Példádban a full katasztrófára kicsi az esély, de a hibára nagyobb a több réteg miatt, nem beszélve a költségekről. Ennek optimuma egyéni preferencia. Sok esetben nem is költség szinten történik a döntés, hanem stratégiai okokból. Ilyen lehet pl az is, hogy egy-egy munkakör keskeny, de mély tudást igényeljen.

Én nem ebben a méretben élek/dolgozom, de értem amit írsz.

Így oké, ezzel egyetértek. Én sem szoktam ágyúval lőni verébre, de azon komolyan megütköztem, hogy a db legyen a frontend kiszolgáló, olyat még kicsi és egyszerű esetben sem tudott senki értelmesen indokolni.

Ha a biztonság nem érdekes, akkor is behoz egy durva problémát, mégpedig hogy sokszor db verzió függő a csatlakozó kliens lib, így főverziót frissíteni is csak új kliens verzió kiadásával együtt lehet. Szerver oldalon ezt tudom egy kézben egy időzítéssel tartani, de a kliensek főleg a homeoffice óta nagyon nehezen vehetők rá időzített együttműködésre, azaz ennek az az eredménye, hogy Mancika majd a pénzügyi zárás napjának reggelén veszi észre, hogy nem tud dolgozni, és persze szar az IT.

Tudom, de lássuk be, ez attól még nem szerencsés. Téged még úgy hívnak oda, hogy kéne egy olcsó megoldás, zárt a hálózatunk, ne bonyolítsd el. Utána beüt a covid, szomszéd Pistike szívességből megoldja nekik hogy távolról is tudjanak dolgozni (vpn bonyolult, router-en kiforgatni könnyebb), és máris kész a baj. 

Meg lehet oldani (majdnem) mindent DB szinten is, de nem erre valo.

Mondjuk szeretned, ha a XY user megnezhesse a sajat relevans rekordjait, a beosztottjaiet, meg ha helyettesiti a nyaralo kollegajat, akkor az o rekordjait csak arra a ket hetre. Ez pl. egy tok egyszeru igeny. Meg lehet oldani a DB szintjen? Persze, korbe lehet takolni egy rakas view-val meg sp-vel, aztan hadd menjen, de en nem javasolnam ezt jo szivvel senkinek.

Ugyanazt a thread-et olvassuk? WPF alkalmazásról beszélünk, milyen internet? Ezek az alkalmazások 99%-ban vállalati, belső hálózaton ülnek, nyugodtan elérhetik közvetlenül a DB szervert.

(hozzáteszem, milliónyi alkalmazás fut pl. azure SQL-re kötve, ami az "interneten" van, semmi gond nincs vele, ezeréve erős titkositással és authentikációval megy az adatbázis forgalom mssql-en)

Miért tudják ott kezelni a usereket, ha az adatbázisban nem? Ennyit azért a mysql is tud.

A legelso kerdesem az volt a temaban, hogy van-e a usernek sajat accountja a DB-hez. Mert jellemzoen nincs. De ha van, es azt elkered, az oke. (Most tegyuk felre a netre logatott MySQL-t, lehet ez VPN-en keresztul is)

Szerintem tulbonyolitod. Az eredeti allitasom: kozos hasznalatu secret, letarolva az alkalmazasban = rossz. Hogy ezt hogy oldod meg, arra van mindenfele opcio.

"kozos hasznalatu secret, letarolva az alkalmazasban = rossz. Hogy ezt hogy oldod meg, arra van mindenfele opcio."

Ebben egyetértünk.

Én arra hegyeztem ki a válaszaimat, hogy ez egy átlag vállalati környezetben, normális DB-vel triviális feladat és nem kell köztes api-t belekeverni. Irtam és üzemeltetek is jópár ilyen alkalmazást.

(de nyilván van olyan a feladat, hogy érdemes közé rakni egy api-t, de a postban nem volt erről szó)

Ez oké.

Példát nem találok WPF EF MySQL app-ra. Hogyan kezeli az adatbáziskapcsolatot, hol példányosít?

A szép megoldást keresem. :)

Pl.: van 3 táblám. Mindegyiket külön formon tartom karban. A DBContext hogyan kezelendő?

DBConext.cs
Class1.cs (egyik tábla)  -> Class1Windows.cs (xaml)
Class2.cs (másik tábla) -> Class2Window.cs (xaml)
Class3.cs (harmadik tábla) -> Class3Window.cs (xaml)
Szerkesztve: 2023. 12. 23., szo – 20:17

Talán ezt kerestem:

https://learn.microsoft.com/en-us/ef/ef6/fundamentals/databinding/wpf?s…

Az ablak (form) onclosing metódusában eldobja az adatbázis context-et.

public partial class MainWindow : Window
        {
            private ProductContext _context = new ProductContext();
            public MainWindow()
            {
                InitializeComponent();
            }
//
// ....
//
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
            {
                base.OnClosing(e);
                this._context.Dispose();
            }

Azaz nem állandó az adatbáziskapcsolat. (Más a logika)

Emailben átküldtem egy "névteret" benne 8 db projektet. (OE-NIK-es példa.)

Benne:

3 db frontend (js, terminal, wpf(MVVM))
1 db endpoint ehhez csatlakoznak a  frontendek (json)
1 db models: lényegében 1:1-ben adatbázistábláknak felelnek meg és a kapcsolataiknak (CodeFirst)
1 db logic : üzleti logika
1 db: repository : db kapcsolat, de lehetne más is, fájl, stream, egy másik app endpointja
1 db test, ami az egész appot teszteli

Az app IoC-t használ,  benne maga a kapcsolat lényegében egy Singleton