2009-09-24 17 views
35

Me gustaría ver una sencilla aplicación de inicio de sesión, no es tan simple como this sin embargo.Seguridad básica en JSF

Lo que me gustaría lograr es comprender cómo funciona JSF, he desarrollado mucho ASP.NET donde tienes el código y donde puedes comprobar si se creó una sesión al iniciar sesión.

Una solución similar en JSF sería grande.

Esto es básicamente lo que quiero lograr:

  • página de entrada
  • SI OK
    • Crear sesión y volver "éxito"
  • SI FALLO
    • retorno "fracaso"

(El "éxito" y el fracaso se asignan a faces-config.xml)

En el éxito páginas Quiero ser Ciertos que el usuario está conectado, por lo que uno no debería ser capaz de navegar a "success.jspx" si no se ha conseguido la sesión correcta.

+1

Relacionados: http://stackoverflow.com/questions/2206911/best-way-for-user-authentication-on-javaee-6-using-jsf-2-0/2207147#2207147 O si está abierto a bibliotecas de terceros como Shiro, luego http://balusc.blogspot.com/2013/01/apache-shiro-is-it-ready-for-java-ee-6.html – BalusC

Respuesta

44

No hay ninguna funcionalidad de autenticación inherente en el núcleo JSF más allá de poder usar cosas como los atributos del componente rendered orientados a la seguridad basada en roles.

De forma predeterminada, una aplicación JSF se basa en los mismos mecanismos de seguridad administrados por contenedor que el componente web que lo contiene (JEE5 tutorial). marcos de 3 ª parte como Seam pueden proporcionar alternativas.

Si desea añadir su seguridad de las aplicaciones, un servlet filter es uno de los mecanismos más sencillos.

Este filtro protege los recursos bajo el directorio restricted como se define en web.xml:

<filter> 
    <filter-name>AuthenticationFilter</filter-name> 
    <filter-class>restricted.AuthenticationFilter</filter-class> 
    </filter> 
    <filter-mapping> 
    <filter-name>AuthenticationFilter</filter-name> 
    <url-pattern>/restricted/*</url-pattern> 
    </filter-mapping> 

La implementación de la clase de filtro:

public class AuthenticationFilter implements Filter { 
    private FilterConfig config; 

    public void doFilter(ServletRequest req, ServletResponse resp, 
     FilterChain chain) throws IOException, ServletException { 
    if (((HttpServletRequest) req).getSession().getAttribute(
     AuthenticationBean.AUTH_KEY) == null) { 
     ((HttpServletResponse) resp).sendRedirect("../restricted_login.faces"); 
    } else { 
     chain.doFilter(req, resp); 
    } 
    } 

    public void init(FilterConfig config) throws ServletException { 
    this.config = config; 
    } 

    public void destroy() { 
    config = null; 
    } 
} 

Un grano de inicio de sesión se define en faces-config.xml:

public class AuthenticationBean { 
    public static final String AUTH_KEY = "app.user.name"; 

    private String name; 
    public String getName() { return name; } 
    public void setName(String name) { this.name = name; } 

    public boolean isLoggedIn() { 
    return FacesContext.getCurrentInstance().getExternalContext() 
     .getSessionMap().get(AUTH_KEY) != null; 
    } 

    public String login() { 
    FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(
     AUTH_KEY, name); 
    return "secret"; 
    } 

    public String logout() { 
    FacesContext.getCurrentInstance().getExternalContext().getSessionMap() 
     .remove(AUTH_KEY); 
    return null; 
    } 
} 

El formulario de inicio de sesión JSF en th e restricted_login.jsp página:

<f:view> 
    <p><a href="restricted/secret.faces">try to go to secret 
    page</a></p> 
    <h:form> 
    Username: 
    <h:panelGroup rendered="#{not authenticationBean.loggedIn}"> 
     <h:inputText value="#{authenticationBean.name}" /> 
     <h:commandButton value="login" 
      action="#{authenticationBean.login}" /> 
     </h:panelGroup> 
     <h:commandButton value="logout" 
     action="#{authenticationBean.logout}" 
     rendered="#{authenticationBean.loggedIn}" /> 
    </h:form> 
    </f:view> 

(La URL de redireccionamiento/mecanismo fue elegido por razones de brevedad en lugar de cualquier tipo de las mejores prácticas; ver el Servlet API para más opciones.)

+0

podría aclarar cómo esto es diferente de seguridad administrada por contenedor? y cómo preferir uno sobre el otro después de considerar las ventajas/desventajas de cada uno? –

+0

@Marcos - realmente merece ser su propia pregunta, posiblemente haciendo referencia a esta. – McDowell

+0

En realidad, ya había publicado algo similar aquí: http: //stackoverflow.com/questions/7872265/protected-urls-leaking-unprotected-components-of-the-webapge-to-unauthenticated/7875236#7875236 –

3

La mejor manera de hacerlo sería utilizar contenedor de seguridad gestionada.

Here is a tutorial sobre cómo lograr eso con glassfish y jsf.

2

Si usa plantillas, he descubierto que realmente no necesita un filtro.

index.jsp

<jsp:forward page="startup.faces"></jsp:forward> 

startup.xhtml (.faces), no podía comprender tratar de mostrar una pantalla, que Calles del startupSubmit Javascript() de la carga y que hace clic en el botón. Esto envía el flujo directamente al método start() en StartupBean.java.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0  Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
. 
. 
<script type="text/javascript"> 
function startupSubmit() { 
    **document.getElementById('startupForm:startupBtn').click();** 
} 
</script> 
<h:body onload="startupSubmit()"> 
<h:form id="startupForm"> 
<p:commandButton id="startupBtn" value="" action="#{startupBean.start}" ajax="false" /> 
</h:form> 
</h:body> 
</html> 

StartupBean.java (no es parte de la template.xhtml abajo). El método start() en StartupBean establece una variable llamada authorised to true (por defecto es false), luego salta a first.xhtml. Puede usar cualquier criterio que desee para determinar si la autorización está establecida en verdadero ... como los criterios de inicio de sesión.

package gov.irs.eservices.managementBeans; 

import javax.faces.bean.ManagedBean; 
import javax.faces.bean.SessionScoped; 

@ManagedBean(name="startupBean") 
@SessionScoped 
public class StartupBean { 

private boolean authorized; 

public StartupBean() { 
} 

public String start() { 
    **setAuthorized(true);** 
    return "first"; 
} 

public boolean isAuthorized() { 
    return authorized; 
} 

public void setAuthorized(boolean authorized) { 
    this.authorized = authorized; 
} 
} 

template.xhtml. En template.xhtml, solo dentro del formulario, coloca un h: o p: panelGrid y solo lo renderiza si startupBean.authorized es verdadero. La única forma en que un usuario puede acceder a las páginas contenidas en la plantilla es primero si comienza a utilizar StartupBean.java.

<f:view> 
<div id="container"> 
<h:form id="templateForm"> 
**<p:panelGrid rendered="#{startupBean.authorized}">** 
    <div id="header"> 
     <ui:include src="header.xhtml" /> 
    </div> 

    <div id="wrapper"> 
     <div id="firstId"> 
      <ui:insert name="first"></ui:insert> 
     </div> 
. 
. <!-- MORE PAGES --> 
. 
. 
    </div> 

    <div id="footer"> 
     <ui:include src="footer.xhtml" /> 
    </div> 
</p:panelGrid> 
</h:form> 
</div>  
</f:view> 

Así que esa es mi solución. Lo probé bastante bien y parece funcionar bien.

+0

The '@ManagedBean El atributo '* name * en' StartupBean' no es necesario ya que obtendrá este nombre de manera predeterminada. – rbento