2012-09-03 11 views
5

Estoy tratando de usar HttpServletRequest.login con autenticación basada en formulario.JSF 2.0: Cómo redirigir a la página protegida después de usar HttpServletRequest.login

Todo está bien (el contenedor dice si el inicio de sesión/contraseña son buenos), excepto que después de que el usuario ingresó su nombre de usuario, no sé cómo redirigirlo a la página protegida que solicitó (el formulario de inicio de sesión se vuelve a mostrar). ¿Como hacer eso?

Gracias de antemano por su ayuda.

El código:

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> 

Página 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> 

Actualización: sin Ajax no funciona.

Copia de frijol:

@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)); 
    } 
    } 

} 

Respuesta

5

En el caso de la autenticación basada en formulario contenedor administrado, la página es de acceso bajo las tapas abiertas por un RequestDispatcher#forward() y la solicitud original URI es por lo tanto disponible como un atributo de la petición con el nombre como identificado por RequestDispatcher#FORWARD_REQUEST_URI. Los atributos de solicitud (básicamente, el alcance de la solicitud) están en JSF disponible en ExternalContext#getRequestMap().

Por lo tanto, esto debería hacer:

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)); 
    } 
} 

sólo es necesario para hacer que el grano de @ViewScoped (JSF) o @ConversationScoped (CDI) en lugar de @SessionScoped (y absolutamente no @RequestScoped, de lo contrario un enfoque diferente necesita ser utilizado con <f:param> y <f:viewParam>).

+0

Funciona (con solo un molde para Cadena paraURI solicitado). ¡Estupendo! BalusC, ¡estaba esperando tu respuesta! He leído sus artículos durante mucho tiempo y siempre los he encontrado muy interesantes y con una gran experiencia. Traté de obtener este URI, pero no pude lograr el buen valor. Su solución con un método init lanzado antes del envío es muy inteligente. Muchas gracias por su ayuda. ¿Dónde consiguió su información? Al leer las fuentes? – user1643352

+1

Solo un comentario: el alcance del bean ** no debe ** ser una sesión porque redirigiría siempre a la misma página (la primera protegida a la que el usuario intentó acceder). He usado el alcance de la vista (es más fácil que el alcance de la conversación). En cuyo caso, el URI solicitado podría ser nulo? – user1643352

+1

En cuanto a cómo lo sabía, bueno, es solo cómo funciona la autenticación administrada por contenedor según la especificación/estándar API de Servlet. Estoy al lado de JSF también muy familiarizado con JSP/Servlet "simple". Y, de hecho, el alcance de la sesión es insuitable, como se contestó. El URI de solicitud de reenvío podría ser 'nulo' si el usuario final solicita directamente la página de inicio de sesión. – BalusC

Cuestiones relacionadas