2012-09-03 16 views
5

Próbuję użyć HttpServletRequest.login z uwierzytelnianiem opartym na formularzu.JSF 2.0: Jak przekierować do strony chronionej po użyciu HttpServletRequest.login

Wszystko jest ok (kontener mówi, czy login/hasło są dobre), z tym wyjątkiem, że po wpisaniu przez użytkownika loginu, nie wiem jak przekierować użytkownika na stronę, której zażądał (formularz logowania jest ponownie wyświetlana). Jak to zrobić?

Z góry dziękuję za pomoc.

Kod:

web.xml:

<login-config> 
    <auth-method>FORM</auth-method> 
    <realm-name>security</realm-name> 
    <form-login-config> 
     <form-login-page>/faces/loginwithlogin.xhtml</form-login-page> 
     <form-error-page>/faces/noaut.xhtml</form-error-page> 
    </form-login-config> 
</login-config> 

Page loginwithlogin.xhtml

<html xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:h="http://java.sun.com/jsf/html" 
    xmlns:f="http://java.sun.com/jsf/core"> 
    <h:head> 
     <title>Authentication</title> 
    </h:head> 
    <h:body> 
     <h:form> 
      Login : 
      <h:inputText value="#{login.login}" required="true" /> 
      <p/> 
      Mot de passe : 
      <h:inputSecret value="#{login.password}" required="true" /> 
      <p/> 
      <h:commandButton value="Connexion" action="#{login.submit}"> 
       <f:ajax execute="@form" render="@form" /> 
      </h:commandButton> 
      <h:messages /> 
     </h:form> 
    </h:body> 
</html> 

Aktualizacja: bez Ajax to nie działa.

kopii fasola:

@Named 
@SessionScoped 
public class Login implements Serializable { 
    private String login; 
    private String password; 
    // getters and setters 
    ... 

    public void submit() { 
    FacesContext context = FacesContext.getCurrentInstance(); 
    HttpServletRequest request = 
      (HttpServletRequest) context.getExternalContext().getRequest(); 
    try { 
     request.login(login, mdp); 
     context.addMessage(null, 
       new FacesMessage(FacesMessage.SEVERITY_INFO, 
       "OK", null)); 
    } catch (ServletException e) { 
     context.addMessage(null, 
       new FacesMessage(FacesMessage.SEVERITY_ERROR, 
       "Bad login", null)); 
    } 
    } 

} 

Odpowiedz

5

W przypadku uwierzytelniania formularz oparty pojemnika udało, strona logowania jest pod kołdrą otwieranych przez RequestDispatcher#forward() i oryginalnego żądania URI jest zatem dostępna jako atrybut żądania z nazwą jako identyfikowane przez RequestDispatcher#FORWARD_REQUEST_URI. Żądania atrybutów (w zasadzie zakres żądania) są dostępne w JSF pod numerem ExternalContext#getRequestMap().

Zatem, należy to zrobić:

private String requestedURI; 

@PostConstruct 
public void init() { 
    requestedURI = FacesContext.getCurrentInstance().getExternalContext() 
     .getRequestMap().get(RequestDispatcher.FORWARD_REQUEST_URI); 

    if (requestedURI == null) { 
     requestedURI = "some/default/home.xhtml"; 
    } 
} 

public void submit() throws IOException { 
    // ... 

    try { 
     request.login(username, password); 
     externalContext.redirect(requestedURI); 
    } catch (ServletException e) { 
     context.addMessage(null, 
       new FacesMessage(FacesMessage.SEVERITY_ERROR, 
       "Bad login", null)); 
    } 
} 

Wystarczy tylko dokonać fasoli @ViewScoped (JSF) lub @ConversationScoped (CDI) zamiast @SessionScoped (i absolutnie nie @RequestScoped; w przeciwnym razie inne podejście powinno być stosowane z <f:param> i <f:viewParam>).

+0

Działa (z tylko rzutem na ciąg dla żądanegoURI). Wspaniały! BalusC, czekałem na twoją odpowiedź! Czytałem twoje artykuły przez długi czas i zawsze uważałem je za bardzo interesujące i posiadające bardzo duże doświadczenie. Próbowałem uzyskać ten identyfikator URI, ale nie udało mi się uzyskać dobrej wartości. Twoje rozwiązanie z metodą init uruchomioną przed przesłaniem jest bardzo sprytne. Bardzo ci dziękuje za pomoc. Skąd masz informacje? Czytając źródła? – user1643352

+1

Tylko uwaga: zakres komponentu bean ** nie musi być ** sesją, ponieważ przekierowuje zawsze na tę samą stronę (pierwszą chronioną, do której użytkownik próbował uzyskać dostęp). Użyłem zasięgu widoku (jest to łatwiejsze niż zakres rozmowy). W takim przypadku żądany identyfikator URI może być pusty? – user1643352

+1

Jeśli chodzi o sposób, w jaki to wiedziałem, to po prostu sposób, w jaki uwierzytelnianie zarządzane przez kontener działa zgodnie ze specyfikacją/standardem API Servlet. Jestem obok JSF również bardzo dobrze znany z "zwykłego" JSP/Servlet. I rzeczywiście, zakres sesji jest niewystarczający, w odpowiedzi. Identyfikator URI żądania przekazania może mieć wartość "null", jeśli użytkownik zażądał bezpośrednio strony logowania. – BalusC

Powiązane problemy