Autor Wątek: Łączenie się aplikacji z bazą danych vs enduser  (Przeczytany 2781 razy)

Offline gemGreg

  • Użytkownik
    • gemGreg's homepage

# Kwiecień 17, 2012, 10:55:53
Witam

Piszę aplikację, która łączy się z bazą danych. Tematyka aplikacji nie jest ważna.
Istotne jest natomiast, że aplikacja umożliwia obsługę wielu użytkownikom, którzy posiadają władne konta.

Zagwozdką dla mnie jest jak rozwiązać sprawę połączenia z bazą danych.

Pomysł 1:
Użytkownik ściąga aplikację w której jest instalka + kod sql bazy, który sobie musi zaimportować do swojej bazy. Użytkownicy i ich hasła są zapisane w tabeli w bazie, a aplikacja się z nią łączy przez podane dane połączenia przy instalacji programu.

Pomysł 2:
Użytkownik ściąga aplikację w której jest instalka + kod sql bazy, który sobie musi zaimportować do swojej bazy. Użytkownicy programu są użytkownikami samej bazy danych i połączenie z bazą następuje indywidualnie. Nie jest wymagane hasło do połączenia przy instalacji (tworzymy w bazie danych konto dla pierwszego użytkownika) (może być problem przy bazie np mysql z ograniczoną ilością użytkowników do np 1)

Oba te pomysły mi zalatują jakimś nieprofesjonalizmem. Pewnie najlepiej było by stworzyć jakąś aplikację serwera autoryzującą użytkowników, ale chciałem tego uniknąć.
Jest jakiś bezpieczny sposób przechowywania connectionstringa w aplikacji klienta?

Jak powiedzmy wdrażam osobiście taką aplikację np w firmie w której pracuję to mogę sobie wkompilować na sztywno połączenie z bazą, ale już jako produkt to nie wchodzi w grę.

Jeśli temat trafił w złe miejsce na forum to proszę o przeniesienie jakiegoś miłego admina hehe.
« Ostatnia zmiana: Kwiecień 17, 2012, 11:12:50 wysłana przez gemGreg »

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Avaj

  • Użytkownik

# Kwiecień 17, 2012, 13:24:33
Ogólnie to raczej powinieneś łączyć się albo z localhostem albo z usługą sieciową, która komunikuje się z bazą danych. W przeciwnym razie ktoś mógłby zrobić lewą aplikację, która łączy się z bazą danych i np. wycina stamtąd wszystkie dane.

http://img820.imageshack.us/img820/1641/itsfinetrustme.png

Offline gemGreg

  • Użytkownik
    • gemGreg's homepage

# Kwiecień 18, 2012, 09:06:10
Ogólnie to raczej powinieneś łączyć się albo z localhostem albo z usługą sieciową, która komunikuje się z bazą danych. W przeciwnym razie ktoś mógłby zrobić lewą aplikację, która łączy się z bazą danych i np. wycina stamtąd wszystkie dane.

http://img820.imageshack.us/img820/1641/itsfinetrustme.png

Mógłbyś rozwinąć myśl odnośnie łączenia się z usługą sieciową? Chodzi o jakiś programik-serwer?
Co do localhosta to jasne, nawet w moim przypadku w większości odbywałoby się to w sieci lokalnej co nie zmienia faktu, że aplikacja gdzieś musi mieć zapisane to hasło do bazy w aplikacji klienskiej (jeśli już mówimy o bezpośrednim połączeniu z bazą).

Offline Kos

  • Użytkownik
    • kos.gd

# Kwiecień 18, 2012, 10:42:23
Uh, Gem, mało zrozumiałem z Twojego opisu. Ile jest tych baz danych w końcu? Gdzie leżą?

Cytuj
Piszę aplikację, która łączy się z bazą danych.
Z jakąś pojedynczą ogólnodostępną bazą danych w necie, OK.
Cytuj
umożliwia obsługę wielu użytkownikom, którzy posiadają władne konta
Jakie konta? Bankowe? Facebookowe? OpenID? Konta w tej bazie? Lokalne konta na danym komputerze? Posiadają tj "już posiadają i chcemy je obsłużyć", czy "mają docelowo posiadać"?

Pomysł 1:

Cytuj
Użytkownik ściąga aplikację w której jest instalka + kod sql bazy
Yyy... W której CO jest? :D W aplikacji jest instalator serwera bazy danych i jej schemat jako SQL? Czy może instalator samej aplikacji + kod do obsługi jednej centralnej bazy danych?
Cytuj
który sobie musi zaimportować do swojej bazy.
Co to jest "swoja baza"? Instancja MySQL lub SQLite na kompie każdego usera?

Cytuj
Użytkownicy i ich hasła są zapisane w tabeli w bazie
Już są? Mają być? Przez kogo?

Pomysł 2:
Cytuj
Użytkownik ściąga aplikację w której jest instalka + kod sql bazy, który sobie musi zaimportować do swojej bazy.
Yyy...
Cytuj
Użytkownicy programu są użytkownikami samej bazy danych i połączenie z bazą następuje indywidualnie.
Indywidualnie, czyli każdy podczas połączenia się uwierzytelnia swoimi danymi

Cytuj
Nie jest wymagane hasło do połączenia przy instalacji
Yy OK,
Cytuj
(tworzymy w bazie danych konto dla pierwszego użytkownika)
Yy...? Tzn jednorazowo: jest w bazie danych jedno konto z limitowanymi uprawnieniami
Cytuj
(może być problem przy bazie np mysql z ograniczoną ilością użytkowników do np 1)
True. Problemu nie ma, jeśli baza jest Twoja.





Z innej strony. Założenia są takie: Masz usługę sieciową (bazę danych), która jest ogólnodostępna przez internet. To, czego szukasz, to sposób na autoryzację: Jest mnóstwo rzeczy, które można zrobić z bazą, a autoryzacja (koncepcyjnie) to sposób na udzielenie odpowiedzi na pytanie: "Mam tu klienta, który chce dodać taki i taki wiersz do tabeli X: Czy mu wolno?".

Praca domowa: Zastanów się, kiedy mu ma być wolno, a kiedy nie. :)

Żeby udzielić odpowiedzi, prawdopodobnie będziesz też musiał odpowiedzieć na pytanie "kto to właściwie jest ten klient" - czyli dokonać uwierzytelniania.



Jak to zrealizować?
To zależy od zasadniczego pytania "czego potrzebujesz?".

1) Jakimś sposobem na autoryzację jest system uprawnień w bazie SQL. Jeżeli każdy user ma mieć dokładnie takie same uprawnienia, być może to jest wszystko, czego potrzebujesz. Wtedy masz w bazie 2 konta: admina i usera, a wjazd na konto usera jest "otwarty": bez hasła lub z hasłem hardkodowanym w samej aplikacji (co w praktyce oznacza dokładnie to samo :D).

Jeśli potrzebujesz dokładniejszej kontroli nad tym, co z konta usera wolno, a co nie, zamiast przydzielać uprawienia do tabelek, możesz zrobić procedury składowane i przydzielić uprawnienia do nich. (Zgaduję, że wtedy już nie MySQL, a np. Postgres, ale w sumie nie wiem ile MySQL potrafi...)

2) Jeżeli każdy user ma mieć możliwość np. wyłącznie dodawać nowe rekordy ORAZ edytować swoje, to żeby określić, które są "swoje", potrzebujesz uwierzytelniania.
Jakimś sposobem na uwierzytelnianie jest mechanizm kont userów w bazie SQL. Niemniej będzie pewien problem z dołożeniem tutaj jakiejś konkretnej logiki: bez prodecur składowanych lub triggerów się już nie obejdziesz, bo jak inaczej wprowadzić zasadę, że "user może kasować tylko rekordy w tabeli Foo w której Foo.owner == currentUserId"?

Pytanie, co z tworzeniem userów. Kto ma ich tworzyć? Gdzieś musi być wystawiona ogólnodostępna usługa, która pozwala na założenie nowego konta. Nie wiem, czy procedury składowane na to pozwalają w MySQL lub PostgreSQL, ale prawdopodobnie pozwalają. Niemniej chciałbyś pewnie wprowadzić tu pewne dodatkowe utrudnienia (jakaś captcha, jakieś potwierdzenia mailem, bzdurki?), by nie było tak łatwo zaspamować bazę nowymi kontami. Poziom komplikacji rośnie i widać, że łatwiej byłoby zrobić to dodatkowym endpointem np. w PHP... Chociaż jestem w stanie wyobrazić sobie rozwiązanie na samych procedurach składowanych mające na celu utrudnienie* stworzenia konta w inny sposób niż przez Twoją aplikację.

*)utrudnienie- i nic ponad to, bo wszystko co user może zrobić z bazą przez Twoją aplikację, może też zrobić samemu po zdekompilowaniu jej :).

Lepsze bazy danych CHYBA dają czasem możliwość podpięcia zewnętrznego systemu autoryzacji, ale nie mam pomysłu jak z tego tu skorzystać.

3) Powyższe wystarczy do systemu funkcjonalnego i bezpiecznego, ale jak nie chcesz trzaskać procedur składowanych lub masz ograniczenie 1 usera na bazę, to można zaimplementować coś analogicznego w inny sposób:

Sam piszesz sobie ogólnodostępny endpoint, np. w PHP (bez znaczenia w czym). Obsługujesz w nim uwierzytelnianie i autoryzację (w dowolny sposób: teraz nie jesteś skazany na mechanizmy zapewnione przez silnik bazy danych, możesz sobie np. sam trzasnąć uwierzytelnianie przez openid albo samemu solić hasełka).
Realizacja autoryzacji... Raczej nie będziesz parsował sam kwerend SQL i sprawdzał, czy "wyglądają czysto". Raczej w takiej sytuacji wystawiasz szereg funkcji do wywołania np. przez HTTP i w każdej najpierw sprawdzasz, czy danemu userowi wolno, a potem wołasz kwerendę do bazy. Więcej swobody, więcej kodu.

Baza danych zatem nie jest już publicznym endpointem, nie uwierzytelnia ani nie autoryzuje - więc zostajesz z jednym userem z pełnymi prawami (= hostujesz łatwo). Wjazd na bazę ma tylko endpoint publiczny.

Offline gemGreg

  • Użytkownik
    • gemGreg's homepage

# Kwiecień 18, 2012, 13:48:21
Może faktycznie napisałem to niezbyt zrozumiale ;)

Przedstawię krótką scenkę sytuacyjną, która zademonstruje jakiego typu aplikacja to jest.

Pracownicy przychodzą do pracy i wykonują sobie jakieś czynności poza komputerem. Co jakiś czas mają obowiązek jednak wejść w moją aplikację, zalogować się na swoje konto i dodać odpowiednie wpisy zależnie od tego co dotychczas zrobili.
Jest też w firmie przydzielona osoba do administrowania aplikacją. Ma też konto w programie o wyższych uprawnieniach. Może dodawać nowe konta, resetować hasła, uzupełniać słowniki, ma wgląd w wprowadzone przez pracowników wpisy, może generować raporty itp.


To jak firma chce rozwiązać kwestie bazy danych zostawiam do indywidualnego wyboru. Wymaganie jest by była to baza mysql. Czy to będzie w localhoscie czy przez internet ma nie mieć znaczenia. Tutaj jest ten cały "kod sql". Bo jakoś na początek trzeba tą strukturę bazy stworzyć (puste tabele, jakieś słowniki domyślne itp). Jak na razie nie robiłem żadnego instalatora, który to będzie tworzył (może kiedyś), więc dostarczam kod tworzący strukturę bazy.

W tym momencie kwestie połączenia z bazą mam rozwiązaną tak, że jest jedno konto w bazie i aplikacja się łączy do niego. A autoryzacja użytkowników odbywa się przez logowanie w aplikacji, która sobie sprawdza w tabeli USER w bazie czy wprowadzono poprawny login i hasło. Nie ma triggerów ani procedur składowanych.

Widzę w tym moim rozwiązaniu właśnie problem, dlatego tu napisałem posta :)

Bo jak aplikacja zna hasło do konta, które wszystko może zrobić z bazą to jeśli ktoś jakoś wydostanie tego connection stringa z programu (gdziekolwiek jest on zapisany czy wkompilowany w exe, czy w zaszyfrowanym pliku), to może wszystko ;)

Samą aplikację mam praktycznie gotową, ale jak na razie łączy się ona na sztywno z moją bazą danych. Chcę więc jakieś w miarę proste do realizacji i bezpieczne rozwiązanie na umożliwienie przyszłemu administratorowi na podłączenie tej aplikacji pod swoją bazę.

ps. Dodam że aplikacja jest napisana w C# :)
« Ostatnia zmiana: Kwiecień 18, 2012, 13:53:00 wysłana przez gemGreg »

Offline Kos

  • Użytkownik
    • kos.gd

# Kwiecień 18, 2012, 14:16:10
Pracownicy przychodzą do pracy i wykonują sobie jakieś czynności poza komputerem. Co jakiś czas mają obowiązek jednak wejść w moją aplikację
Gdzie się wchodzi w Twoją aplikację? Jest jeden komputer w firmie i sobie do niego podchodzą, z dowolnego komputera przez sieć?

Cytuj
To jak firma chce rozwiązać kwestie bazy danych zostawiam do indywidualnego wyboru. Wymaganie jest by była to baza mysql.
No to do wyboru rzeczywiście. :-)

Cytuj
Czy to będzie w localhoscie czy przez internet ma nie mieć znaczenia.
Noo, powiedziałbym że to ma fundamentalne znaczenie, czy gromadzone przez Twoją aplikację dane mają być zcentralizowane czy nie. Określ się, bez tego nie ma jak dyskutować dalej.

Cytuj
Tutaj jest ten cały "kod sql". Bo jakoś na początek trzeba tą strukturę bazy stworzyć (puste tabele, jakieś słowniki domyślne itp).
Jak jest jedna baza na wszystkich userów, to raczej nie program kliencki ma to robić, tylko administrator, nie?

Offline gemGreg

  • Użytkownik
    • gemGreg's homepage

# Kwiecień 18, 2012, 14:39:24
Gdzie się wchodzi w Twoją aplikację? Jest jeden komputer w firmie i sobie do niego podchodzą, z dowolnego komputera przez sieć?
Baza danych jest jedna centralna. Może być dowolna ilość stanowisk z aplikacją, a userzy mogą na dowolnym stanowisku się na swoje konto zalogować.

No to do wyboru rzeczywiście. :-)
No wyborem jest czy offline w sieci lokalnej czy przez neta :P

Czy to będzie w localhoscie czy przez internet ma nie mieć znaczenia.
Noo, powiedziałbym że to ma fundamentalne znaczenie, czy gromadzone przez Twoją aplikację dane mają być zcentralizowane czy nie. Określ się, bez tego nie ma jak dyskutować dalej.
Wg. mnie to czy będzie offline czy online nie ma związku z tym czy baza będzie centralnie czy nie. W obu tych przypadkach będzie centralnie.

Jak jest jedna baza na wszystkich userów, to raczej nie program kliencki ma to robić, tylko administrator, nie?
Nie rozbijałem aplikacji na klienta i na admina. Zależnie od tego jakie ma twoje konto uprawnienia to możesz robić.
« Ostatnia zmiana: Kwiecień 18, 2012, 14:43:05 wysłana przez gemGreg »

Offline Kos

  • Użytkownik
    • kos.gd

# Kwiecień 19, 2012, 22:22:24
No wyborem jest czy offline w sieci lokalnej czy przez neta :P
Żaden wybór z Twojej strony, kwestia wklepania odpowiedniego IP samej bazy gdzieś w configu :-).

Cytuj
Nie rozbijałem aplikacji na klienta i na admina. Zależnie od tego jakie ma twoje konto uprawnienia to możesz robić.

No dobra, ale paczkować każdemu userowi w instalatorze serwer MySQL tylko po to, by jeden administrator z niego skorzystał?
Zrób instalator bazy jako osobny program.



Wyjaśniłem wszystko, czy masz jeszcze jakieś niejasności?

Offline gemGreg

  • Użytkownik
    • gemGreg's homepage

# Kwiecień 20, 2012, 15:01:09
No dobra, ale paczkować każdemu userowi w instalatorze serwer MySQL tylko po to, by jeden administrator z niego skorzystał?
Zrób instalator bazy jako osobny program.
Serwera bazy nie zamieszczam przecież z aplikacją. Serwer już sobie trzeba we własnym zakresie mieć / zainstalować.

Co do tego czy rozwiązałeś mój problem.

Kilka rozwiązań mi podałeś. Rozwiązanie z endpointem mi się chyba najbardziej podoba. Chciałbym jednak uniknąć pisania czegoś co by musiało gdzieś działać non stop w tle i zarządzać autoryzacją. A połączenie aplikacji C# i skryptu php hmm. Nie bardzo wyobrażam sobie jak to zrealizować.

Co do tego jak to robię teraz to jednak nie ma chyba bezpiecznej metody na połączenie program <-> baza z jednym kontem wszystko-mogącym w bazie.
« Ostatnia zmiana: Kwiecień 20, 2012, 15:03:07 wysłana przez gemGreg »

Offline Kos

  • Użytkownik
    • kos.gd

# Kwiecień 20, 2012, 18:44:25
Cytuj
A połączenie aplikacji C# i skryptu php hmm. Nie bardzo wyobrażam sobie jak to zrealizować.

Olaboga, jak piszesz w C#, to endpoint piszesz w C#, a nie w PHP :-) Wtedy możesz sobie zrobić komunikację klient-serwer nie przez HTTP, ale wygodniej przez WCF na przykład.

Kilka rozwiązań mi podałeś. Rozwiązanie z endpointem mi się chyba najbardziej podoba. Chciałbym jednak uniknąć pisania czegoś co by musiało gdzieś działać non stop w tle i zarządzać autoryzacją.

Uch, tu jest albo-albo :)
Chcesz zcentralizowane dane, więc potrzebujesz usługę, ogólnodostepną w sieci (jakiejś sieci). Ogólnodostępna usługa w sieci to zawsze jest program, który ciągle działa.

I teraz ta usługa albo pozwala na robienie czegokolwiek, albo realizuje jakiś mechanizm autoryzacji i jest bezpieczna. Przykładowe mechanizmy autoryzacji Ci już opisałem wcześniej; powtórzę:
- jeśli ogólnodostępną usługą jest serwer bazy danych, to autoryzacją może być jej system kont i uprawnień;
- jeżeli ogólnodostępną usługę sam piszesz (w czymkolwiek), to autoryzację robisz sobie jak chcesz. Baza danych, jeśli jakaś jest, to nie jest ogólnodostępna, nie służy jako endpoint.

Jeżeli będziesz miał ogólnodostępny endpoint, który nie będzie wcale autoryzował (patrz: to co wkleił avaJ; serwer MySQL jest endpointem, a hasło pełnego dostępu jest ogólnodostępne, przez co nie ma autoryzacji), to masz dziurę w bezpieczeństwie.

Offline gemGreg

  • Użytkownik
    • gemGreg's homepage

# Kwiecień 21, 2012, 13:57:08
Dzięki za udzielone informacje Kos.
Mam nadzieję, że ktoś kiedyś z tej wiedzy też skorzysta wchodząc tu.
Zobaczę co mi się uda wynegocjować w firmie. Aplikacja działająca w tle na serwerze czy możliwość dodania około 30 userów do mysqla ;) Jak się potem zdecyduję tą aplikację rozpowrzechniać dalej to pewnie napiszę w stylu: client <-> serwerek <-> baza.