2012-11-16 8 views
9

Właśnie zacząłem uczyć się Java EE. Moim celem jest wdrożenie portalu internetowego (z EJB 3 i JSF) dla graczy w badmintona, w którym użytkownicy mogą publikować i analizować swoje wyniki.Zabezpieczenia Java EE - Nie przekierowano na początkową stronę po zalogowaniu

Aby zachować prostotę (dobrze, okazuje się, że tak naprawdę nie jest) postanowiłem użyć systemu bezpieczeństwa, który zapewnia pojemnik (JBoss as7). Po pewnym problemie udało mi się uzyskać uwierzytelnienie/autoryzację do działania. Mam jednak jeden problem, którego nie byłem w stanie rozwiązać.

Gdy próbuję uzyskać dostęp do chronionej strony, otrzymuję zgodnie z oczekiwaniami przechwycone przez system bezpieczeństwa. Jednak po zalogowaniu się nie przekierowuję mnie na stronę, o którą prosiłem. Zamiast tego jestem ponownie poproszony o zalogowanie. Jeśli ręcznie wpisz pierwotny adres, mogę uzyskać dostęp do strony bez żadnych problemów.

Przeczytałem wiele wątków na stackoverflow, ale nie byłem w stanie rozwiązać mojego problemu. Byłbym wdzięczny, gdyby ktoś mógł mi pomóc!

Authentication.java:

@ManagedBean 
@SessionScoped 
public class Authentication { 

    private String username = ""; 
    private String password = ""; 

    private User user = new User(); 

    @EJB 
    UserService service; 

    public String getUsername() { 
     return username; 
    } 

    public void setUsername(String username) { 
     this.username = username; 
    } 

    public String getPassword() { 
     return password; 
    } 

    public void setPassword(String password) { 
     this.password = password; 
    } 

    public User getUser() { 
     return user; 
    } 

    public void login() { 
     FacesContext context = FacesContext.getCurrentInstance(); 
     HttpServletRequest request = (HttpServletRequest) context 
      .getExternalContext().getRequest(); 

     try { 
      Principal userPrincipal = request.getUserPrincipal(); 
      if (userPrincipal != null) { 
       request.logout(); 
      } 
      request.login(username, password); 
      user = service.find(username, password); 
     } catch (ServletException e) { 
      context.addMessage(null, new FacesMessage("Unknown login")); 
     } 
    } 

    public String logout() { 
     FacesContext.getCurrentInstance().getExternalContext() 
      .invalidateSession(); 
     return "login"; 
    } 
} 

login.xhtml

<h:body> 
    <h:form> 
     <h:outputLabel for="username" value="Username" /> 
     <h:inputText id="username" value="#{authentication.username}" required="true" /> 
     <h:message for="username" /> 
     <br /> 
     <h:outputLabel for="password" value="Password" /> 
     <h:inputSecret id="password" value="#{authentication.password}" required="true" /> 
     <h:message for="password" /> 
     <br /> 
     <h:commandButton value="Login" action="#{authentication.login()}" /> 
     <h:messages globalOnly="true" /> 
    </h:form> 
</h:body> 

home.xhtml

<!DOCTYPE html> 
<html xmlns='http://www.w3.org/1999/xhtml' 
xmlns:f='http://java.sun.com/jsf/core' 
xmlns:h='http://java.sun.com/jsf/html' 
xmlns:ui='http://java.sun.com/jsf/facelets' 
xmlns:p="http://primefaces.org/ui"> 
<h:head> 
    <link type="text/css" rel="stylesheet" 
     href="#{request.contextPath}/themes/cupertino/skin.css" /> 
</h:head> 
<h:body> 
    <h:form> 
     <h:commandButton action="login" value="Log in" /> 
    </h:form> 
</h:body> 

web.xml

.... 
<display-name>BadmintonPortal</display-name> 
<welcome-file-list> 
    <welcome-file>/pages/protected/user/user_home.xhtml</welcome-file> 
</welcome-file-list> 
<servlet> 
    <servlet-name>Faces Servlet</servlet-name> 
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> 
    <load-on-startup>1</load-on-startup> 
</servlet> 
<servlet-mapping> 
    <servlet-name>Faces Servlet</servlet-name> 
    <url-pattern>/faces/*</url-pattern> 
    <url-pattern>*.jsf</url-pattern> 
    <url-pattern>*.xhtml</url-pattern> 
</servlet-mapping> 
<context-param> 
    <param-name>primefaces.THEME</param-name> 
    <param-value>cupertino</param-value> 
</context-param> 

<!-- Protected area definition --> 
<security-constraint> 
    <web-resource-collection> 
     <web-resource-name>Restricted Area - ADMIN Only</web-resource-name> 
     <url-pattern>/pages/protected/admin/*</url-pattern> 
    </web-resource-collection> 
    <auth-constraint> 
     <role-name>admin</role-name> 
    </auth-constraint> 
</security-constraint> 
<security-constraint> 
    <web-resource-collection> 
     <web-resource-name>Restricted Area - USER and ADMIN</web-resource-name> 
     <url-pattern>/pages/protected/user/*</url-pattern> 
    </web-resource-collection> 
    <auth-constraint> 
     <role-name>user</role-name> 
     <role-name>admin</role-name> 
    </auth-constraint> 
</security-constraint> 

<!-- Login page --> 
<login-config> 
    <auth-method>FORM</auth-method> 
    <form-login-config> 
     <form-login-page>/pages/public/login.xhtml</form-login-page> 
     <form-error-page>/pages/public/loginError.xhtml</form-error-page> 
    </form-login-config> 
</login-config> 

<!-- System roles --> 
<security-role> 
    <role-name>admin</role-name> 
</security-role> 
<security-role> 
    <role-name>user</role-name> 
</security-role> 

Edit:

Zapomniałem obejmują Faces-config.xml plik

<?xml version="1.0" encoding="UTF-8"?> 

<faces-config xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_1.xsd" 
    version="2.1"> 

    <navigation-rule> 
     <navigation-case> 
      <from-outcome>login</from-outcome> 
      <to-view-id>/pages/protected/user/user_home.xhtml</to-view-id> 
      <redirect/> 
     </navigation-case> 
    </navigation-rule> 
</faces-config> 

jboss-web.xml

<?xml version='1.0' encoding='UTF-8'?> 

<jboss-web> 
    <context-root>BadmintonPortal</context-root> 
    <security-domain>java:/jaas/BadmintonPortalRealm</security-domain> 
</jboss-web> 

Edit 2:

Roztwór roboczy

@ManagedBean 
@ViewScoped 
public class Authentication { 
    ... 
    public Authentication() { 
     ExternalContext eContext = FacesContext.getCurrentInstance() 
      .getExternalContext(); 
     uri = (String) eContext.getRequestMap().get(
      RequestDispatcher.FORWARD_REQUEST_URI); 
    } 

    public void login() { 
     FacesContext context = FacesContext.getCurrentInstance(); 
     HttpServletRequest request = (HttpServletRequest) context 
      .getExternalContext().getRequest(); 

     try { 
      Principal userPrincipal = request.getUserPrincipal(); 
      if (userPrincipal != null) { 
       request.logout(); 
      } 
      request.login(username, password); 
      user = service.find(username, password); 
      context.getExternalContext().getSessionMap().put("user", user); 
      context.getExternalContext().redirect(uri); 
     } catch (ServletException e) { 
      context.addMessage(null, new FacesMessage("Unknown login")); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public String logout() { 
     FacesContext.getCurrentInstance().getExternalContext() 
      .invalidateSession(); 
     return "login"; 
    } 
} 
+0

Jakiej domeny bezpieczeństwa używasz (zdefiniowanej w WEB-INF/jboss-web.xml)? Wygląda na to, że nie polegasz na modelu uwierzytelniania JBoss w 100%. Moduł logowania powinien być zgodny z tym modelem: https://community.jboss.org/wiki/SecureAWebApplicationUsingACustomForm. Jeśli postępujesz zgodnie z tym modelem, nie musisz implementować żadnego komponentu bean uwierzytelniania. – Toni

+0

Dodałem pliki faces-config i jboss-web. Na razie zachowałem je tak proste, jak to tylko możliwe. Powodem, dla którego zaimplementowałem komponent bean uwierzytelniania, było użycie znacznika (a tym samym możliwość użycia priorytetów). – Toss

+0

To ciekawe, więc tak naprawdę nie używasz domeny bezpieczeństwa, prawda? – Toni

Odpowiedz

8

Bierzesz nad częścią logowania za pomocą formularza JSF, która wykonuje programowe logowanie w komponencie zarządzanym JSF po przesłaniu. Jeśli używasz zwykłego formularza HTML, który jest przesyłany bezpośrednio do adresu URL zarządzanego kontenera j_security_check, jak opisano w pierwszej części this answer, to rzeczywiście zostaniesz automatycznie przekierowany na stronę początkową.

Ponieważ jednak logujesz się sam, korzystając z JSF, powinieneś także przejść do strony początkowej używając JSF.Ponieważ strona logowania jest zwykle otwierana po stronie serwera po stronie serwera przez RequestDispatcher#forward(), początkowo żądana strona jest dostępna jako atrybut żądania o nazwie określonej w stałej RequestDispatcher.FORWARD_REQUEST_URI. Pod względem JSF, to w ten sposób dostępne w następujący sposób:

String originalURI = (String) externalContext.getRequestMap().get(RequestDispatcher.FORWARD_REQUEST_URI); 

(należy pamiętać, aby mieć URL awaryjnej dla przypadku zwraca null, tj kiedy to został otwarty bezpośrednio bez uderzania ograniczoną pierwszy URL)

Najlepszym miejscem do ich zebrania byłby (post) konstruktor fasoli @ViewScoped powiązany ze stroną logowania. Z bieżącej sesji scoped podejście Bean, że to prawdopodobnie lepiej, aby to widok scoped jeden i podczas logowania wyraźnie umieścić User w zakresie sesji w następujący sposób:

externalContext.getSessionMap().put("user", user); 

ten sposób użytkownik jest dostępny przez #{user} bezpośrednio zamiast #{authentication.user}.

+0

Dzięki za Twój wkład! Otrzymuję null z mapy RequestMap, więc nadal nie działa :(Masz jakieś pomysły? – Toss

+0

Czy zmieniłeś komponent bean na widok z podglądem? Czy trafiasz na ograniczoną stronę zamiast bezpośrednio na stronę logowania ja? – BalusC

+1

Mam to działa.Przesyłam wywołanie getRequestMap do konstruktora.Teraz działa jak charm. Dziękuję bardzo BalusC, Wyciągam włosy na zewnątrz próbując uzyskać to do pracy – Toss

Powiązane problemy