2012-05-11 16 views
8

Spędziłem cały dzień na wyszukiwaniu i szukaniu różnych pytań tutaj, próbując wymyślić najlepsze rozwiązanie do wdrożenia uwierzytelniania i autoryzacji. Znalazłem część rozwiązania teraz, ale mam nadzieję, że ktoś może wypełnić luki. Zdaję sobie sprawę, że jest dużo tekstu poniżej, ale proszę pokrywa się ze mną: o)JSF: Uwierzytelnianie i autoryzacja, najlepsza droga do przodu

Tle

mam odziedziczyła część wypełnionego wniosku CRM która obecnie używa JSF 2.0, JavaEE 6, WZP i PostgreSQL Baza danych. Niestety, ludzie, którzy początkowo budowali tę aplikację internetową w swojej nieskończonej mądrości, zdecydowali, że najlepiej będzie pozostawić uwierzytelnienie/autoryzację do końca - teraz muszę to wprowadzić.

Wniosek jest zasadniczo podzielony na trzy warstwy - widoki, zarządzana fasola i DAO. Oznacza to, że zarządzane ziarna są szczególnie "grube", ponieważ zawierają całą logikę biznesową, walidację i logikę nawigacji.

wymagania uwierzytelniania/autoryzacji

  1. formularze oparte uwierzytelniania, weryfikacji oparciu o dane przechowywane w bazie danych PostgreSQL.
  2. Jedyną stroną, która będzie publicznie dostępna (przez anonimowych użytkowników), będzie strona logowania.
  3. Muszę uniemożliwić dostęp do niektórych obszarów aplikacji w zależności od roli użytkownika. Na przykład tylko użytkownicy z rolą "Administrator" powinni mieć dostęp do strony tworzenia/edytowania użytkownika.
  4. Potrzebuję również mieć możliwość ograniczenia dostępu do niektórych obszarów strony. Na przykład użytkownik z rolą "Przedstawiciel handlowy" powinien móc wyświetlić szczegóły dotyczące klientów, ale przycisk Zapisz/edytuj powinien być wyświetlany tylko wtedy, gdy użytkownik ma rolę "Obsługa klienta".

Gdzie jestem na

Pierwszą rzeczą, jaką planujesz robić to do tej User Authentication and Authorization using JAAS and Servlet 3.0 Login przykład. Uważam, że spełni moje pierwsze 3 wymagania.

Aby pokazać/ukryć przyciski zapamiętywania itp. Na stronach, mogę skorzystać z techniki opisanej w artykule this SO answer. To częściowo rozwiąże wymaganie 4, jednak uważam, że nadal muszę zabezpieczyć metody działania i lub zarządzane ziarna. Na przykład chciałbym móc dodać adnotację lub coś do metody save() w komponencie bean klienta, aby zapewnić, że tylko użytkownicy z rolą "Customer Service" mogą ją nazwać - tutaj zaczynam napotykać problemy .

Myślę, że jedną z opcji byłoby zrobienie czegoś podobnego do tego, co proponuję zrobić w widoku i użycie faceContext, aby sprawdzić, czy bieżący użytkownik "jest w roli". Nie przepadam za tym, bo to po prostu zaśmieje mój kod i wolałbym zamiast tego używać adnotacji. Gdybym jednak podążał tą drogą, w jaki sposób zwrócę stan http 403?

Adnotacje javax.annotation.security. * Wydają się być dobrym rozwiązaniem do deklaratywnego definiowania dostępu do obszarów aplikacji, jednak z tego co rozumiem, mogą być dodawane tylko do komponentów EJB. To oznaczałoby, że musiałbym przenieść całą logikę biznesową z zarządzanych komponentów, tam gdzie aktualnie znajduje się w nowych EJB. Sądzę, że miałoby to dodatkową zaletę, polegającą na oddzieleniu logiki biznesowej od jej własnego zestawu klas (delegatów, usług lub cokolwiek innego, jak je nazwiesz).Byłby to jednak dość duży reaktor, który nie będzie wspomagany brakiem testów jednostkowych lub testów integracyjnych. Nie jestem pewien, czy odpowiedzialność za kontrolę dostępu powinna również spoczywać na tym nowym poziomie usług - myślę, że powinno to być na zarządzanych ziarnach.

Inne alternatywy

podczas moich badań znalazłem wiele osób wymieniających ram takich jak wiosny i szew. Mam pewne ograniczone doświadczenie z Seamem, myślę, że byłby odpowiedni dla tego projektu i z tego, co pamiętam, uważam, że rozwiązuje problemy z autoryzacją, które mam, ale myślę, że jest już za późno, aby wprowadzić go teraz .

Widziałem również Shiro wspomniano w różnych miejscach. Po spojrzeniu na 10 minute tutorial wyglądało to na dobre dopasowanie, zwłaszcza w połączeniu z Deluan Quintao's taglib, ale nie byłem w stanie znaleźć żadnych tutoriali lub przykładów, jak zintegrować go z aplikacją internetową JSF.

Inną alternatywą, z którą zetknąłem się zaskakująco regularnie, jest wdrożenie niestandardowego rozwiązania - wydaje mi się to szalone!

Podsumowanie

Podsumowując więc, naprawdę chciałbym pewne wskazówki dotyczące tego, czy jadę w dół właściwą drogę w zakresie realizacji uwierzytelniania i autoryzacji oraz w jaki sposób wypełnić tym brakującym elementem zabezpieczającym osoby metody i/lub zarządzany fasoli (lub przynajmniej kod oni przekazać) i/lub w jaki sposób można ręcznie zwrócić stanu HTTP 403.

+1

> Nie udało mi się znaleźć żadnych samouczków ani przykładów, jak zintegrować go z aplikacją internetową JSF. - Jest jeden, ale nadal nie jest idealny: http://balusc.blogspot.com/2013/01/apache-shiro-is-it-ready-for-java-ee-6.html –

Odpowiedz

3

Po przeprowadzeniu wielu badań doszedłem do wniosku, że po pierwsze, wymagania mojej aplikacji będą korzystne, gdy zostaną wdrożone na serwerze aplikacji, który w pełni implementuje specyfikację Java EE, a nie kontener serwletu, taki jak Tomcat. Ponieważ projekt, nad którym pracuję, wykorzystuje Mavena, kluczową sprawą było prawidłowe skonfigurowanie zależności - nie było to łatwe i wymagało sporo wysiłku związanego z szukaniem i błędami: jestem pewien, że istnieje bardziej naukowe podejście, które można wziąć.

Musiałem wtedy create a mysql module, aby moja aplikacja poprawnie rozmawiała z bazą danych, a następnie usunąć fabrykę, która została zaimplementowana do tworzenia DAO i zamiast tego konwertować je do EJB. Musiałem również zaktualizować plik hibernate.cfg.xml, aby odnieść się do dodanego źródła danych i pliku persistence.xml, aby ustawić typ transakcji na JTA, a także odwołać się do źródła danych JTA. Jedyną inną komplikacją było to, że używany był wzorzec Open Session In View, co oznaczało, że otrzymałem leniwy inicjalizacji hibernacji, gdy podmioty były dostępne w widokach. Ponownie zaimplementowałem filtr pokazany na dole tej odpowiedzi, aby obejść ten problem. Uważam, że jest to tymczasowy środek, który sprawi, że wszystko znów będzie działać, zanim będę mógł, mam nadzieję, odnowić ten obszar i usunąć potrzebę filtra.

Przeprowadzka do JBoss zajęła niewiele ponad jeden dzień i jestem pewna, że ​​można by zrobić to znacznie szybciej, gdybym był bardziej doświadczony w Java EE i Maven. Teraz, gdy znajduję się w tym momencie, jestem w dobrej sytuacji, by móc rzucić 3 zabezpieczenia na projekt i wykorzystać to, zamiast próbować zhakować razem rozwiązanie, które w zasadzie jest kierunkiem, jaki zamierzałem podjąć. Fajną cechą Seam 3 jest to, że możesz w pewnym stopniu wybrać i wybrać moduły, których używasz, zamiast dodawać całe ramy (jak Seam 2). Myślę, że wiele innych modułów również będzie pomocnych i pomoże mi między innymi pozbyć się wzorca otwartej sesji.

Jedną z rzeczy, które dotyczyły mnie przy użyciu szwu, było to, że powiedziano mi o DeltaSpike. Wygląda na to, że prawdopodobnie zastąpi szew i nie ma planów dla kolejnych wersji szwu. Zdecydowałem, że skoro seam jest nadal wspierany i jeśli DeltaSpike trwa tak długo, aby osiągnąć efekt 3, to całkiem bezpiecznie jest używać szwu 3.

Mam nadzieję, że uda mi się napisać odpowiedni post na blogu opisujący ta migracja we właściwych szczegółach.

public class OSVRequestFilter implements Filter { 

    private static final String UserTransaction = "java:comp/UserTransaction"; 

    private static Logger logger = LoggerFactory.getLogger(EntityManagerRequestFilter.class); 

    public void init(FilterConfig config) throws ServletException { 
    } 

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 
     if (request instanceof HttpServletRequest) { 
      doFilter(request, response, chain, getUserTransaction()); 
     } 
    } 

    private UserTransaction getUserTransaction() throws ServletException { 
     try { 
      Context ctx = new InitialContext(); 
      return (UserTransaction)PortableRemoteObject.narrow(ctx.lookup(UserTransaction), UserTransaction.class); 
     } 
     catch (NamingException ex) { 
      logger.error("Failed to get " + UserTransaction, ex); 
      throw new ServletException(ex); 
     } 
    } 

    private void doFilter(ServletRequest request, ServletResponse response, FilterChain chain, UserTransaction utx) throws IOException, ServletException { 
     try { 
      utx.begin(); 

      chain.doFilter(request, response); 

      if (utx.getStatus() == Status.STATUS_ACTIVE) 
       utx.commit(); 
      else 
       utx.rollback(); 
     } 
     catch (ServletException ex) { 
      onError(utx); 
      throw ex; 
     } 
     catch (IOException ex) { 
      onError(utx); 
      throw ex; 
     } 
     catch (RuntimeException ex) { 
      onError(utx); 
      throw ex; 
     } 
     catch (Throwable ex){ 
      onError(utx); 
      throw new ServletException(ex); 
     } 
    } 

    private void onError(UserTransaction utx) throws IOException, ServletException { 
     try { 
      if ((utx != null) && (utx.getStatus() == Status.STATUS_ACTIVE)) 
       utx.rollback(); 
     } 
     catch (Throwable e1) { 
      logger.error("Cannot rollback transaction", e1); 
     } 
    } 

    public void destroy() { 
    } 
} 
2

próbowałeś coś ze sprężyną bezpieczeństwa - Najnowsze istota wersji 3

http://janistoolbox.typepad.com/blog/2010/03/j2ee-security-java-serverfaces-jsf-spring-security.html

http://ocpsoft.org/java/jsf-java/spring-security-what-happens-after-you-log-in/

zamiast przy użyciu filtra zgłoszeniowego lub za pomocą JAAS, bezpieczeństwo sprężyna jest kompleksowe ramy bezpieczeństwa, który będzie rozwiązać większość twoich obaw o bezpieczeństwo. Można go użyć do uwierzytelnienia użytkownika za pomocą domeny db, autoryzowania go i przekierowania w razie potrzeby na podstawie dostarczonych informacji uwierzytelniających.

można zabezpieczyć metod, które zostały napisane http://blog.solidcraft.eu/2011/03/spring-security-by-example-securing.html

@PreAuthorize ("hasRole ('ROLE_XXX')") jest sposobem

aby pewne elementy strony bezpiecznej .. // treść

więcej czytania i przykłady http://static.springsource.org/spring-security/site/petclinic-tutorial.html

+0

Dziękuję za odpowiedź. Odbieram twoją radę, ale przy odrobinie wysiłku - zamiast tego użyję bezpieczeństwa szwów: O) – s1mm0t

Powiązane problemy