2011-04-14 24 views
5

Quiero crear un filtro de autorización para mi aplicación web (Para poder restringir el acceso a ciertas páginas).Analizando un documento XML simple con JAXP (JEE6)

he creado un archivo .xml sencillo con las páginas que se permite a cada usuario a visitar:

<access> 
    <buyer> 
     <page>buyoffer.xhtml</page> 
     <page>faq.xhtml</page> 
     <page>index.jsp</page> 
     <page>login.xhtml</page> 
     <page>main.xhtml</page> 
     <page>registrationSucceded.xhtml</page>  
    </buyer> 
    <seller> 
     <page>sellerpanel.xhtml</page> 
     <page>faq.xhtml</page> 
     <page>index.jsp</page> 
     <page>login.xhtml</page> 
     <page>main.xhtml</page> 
     <page>registrationSucceded.xhtml</page>  
    </seller> 
    <administrator> 
     <page>sellerpanel.xhtml</page> 
     <page>faq.xhtml</page> 
     <page>index.jsp</page> 
     <page>login.xhtml</page> 
     <page>main.xhtml</page> 
     <page>registrationSucceded.xhtml</page>  
    </administrator> 
</access> 

Entonces tengo que hacer el análisis para extraer el valor de las páginas, para poder crear las condiciones para permitir o redirigir (Dependiendo). Solo necesito que alguien diga cómo extraer los valores de esas páginas del xml. Esto es lo que hice hasta ahora:

public class RestrictPageFilter implements Filter { 

    private FilterConfig fc; 
    private DocumentBuilder builder; 
    private Document document; 

    public void init(FilterConfig filterConfig) throws ServletException { 
     // The easiest way to initialize the filter 
     fc = filterConfig; 
     // Get the file that contains the allowed pages 
     File f = new File("/allowedpages.xml"); 
     // Prepare the file parsing 
     try { 
      builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); 
      document = builder.parse(f); 
     } catch (ParserConfigurationException e) { 
      e.printStackTrace(); 
     } catch (SAXException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

    } 

    public void doFilter(ServletRequest request, ServletResponse response, 
      FilterChain chain) throws IOException, ServletException { 

     HttpServletRequest req = (HttpServletRequest) request; 
     HttpServletResponse resp = (HttpServletResponse) response; 
     HttpSession session = req.getSession(true); 
     String pageRequested = req.getRequestURL().toString(); 

     // Get the value of the current logged user 
     Role currentUser = (Role) session.getAttribute("userRole"); 
     if (currentUser != null) { 
      if(currentUser.getType().equals("BUYER")) { 
       //Loop BUYER Element of the .xml 
       //if pageRequested.contains(value of the page at buyer element)    
       // chain.doFilter(request, response); 
       // Else 
       // Redirect the user to the main page 
      } 
      else if(currentUser.getType().equals("SELLER")) { 
       //Same as above just for seller element 
      } 
      else if(currentUser.getType().equals("ADMINISTRATOR")) { 
       //Same as above just for administrator element 
      }   
     } 
    } 

    public void destroy() { 
     // Not needed 
    } 
} 

En los comentarios dentro del método doFilter se explica lo que tengo que hacer. ¿Podría alguien darme un consejo sobre cómo debo repetir el archivo para encontrar los nombres de página para cada uno de los tipos de usuario? Intento seguir ejemplos de JAXP de Internet, pero son más complejos de lo que necesito.

actualización el XML se almacena en WEB-INF/classes

Respuesta

9

Bastante uso JAXB. JAXP es una API antigua y muy detallada. JAXB se apoya en Javabeans y, por lo tanto, es limpio y relativamente fácil. Primero crea un Javabean que mapea 1: 1 en el archivo XML usando las anotaciones javax.xml.bind.

@XmlRootElement 
public class Access { 

    @XmlElement 
    private User buyer; 

    @XmlElement 
    private User seller; 

    @XmlElement 
    private User administrator; 

    public User getBuyer() { 
     return buyer; 
    } 

    public User getSeller() { 
     return seller; 
    } 

    public User getAdministrator() { 
     return administrator; 
    } 

    public static class User { 

     @XmlElement(name="page") 
     private List<String> pages; 

     public List<String> getPages() { 
      return pages; 
     } 

    } 

} 

continuación, ejecutar el siguiente fragmento de hacer un mapa (suponiendo que allowedpages.xml se coloca en la raíz de la ruta de clase).

InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream("allowedpages.xml"); 
Access access = (Access) JAXBContext.newInstance(Access.class).createUnmarshaller().unmarshal(input); 

cuenta que no se debe utilizar para este new File(). Vea también getResourceAsStream() vs FileInputStream.

Por último se puede acceder a todas las páginas del comprador de la siguiente manera:

List<String> buyerPages = access.getBuyer().getPages(); 
// ... 

Ni que decir tiene que la seguridad homegrowing no es siempre la mejor práctica. Java EE 6 se envía con seguridad administrada por contenedor.

+0

+1 para la seguridad de la homegrowing no es la mejor práctica – ahvargas

+0

Me encantaría usar la seguridad administrada por contenedor, porque sé que es mejor, es solo que tengo dificultades para implementarlo en mi escenario. Creo que hasta que aprenda un poco más me mantendré en este enfoque. P.S ¿Debo agregar algo al archivo web.xml? – sfrj

+0

Nada. Lo anterior es realmente todo lo que necesita hacer para leer el XML. JAXB ya viene incluido con contenedores Java EE 6 (sé que estás usando Glassfish). En Tomcat, tendrías que instalarlo y configurarlo por separado. – BalusC

0

uso NodeList nodes = document.getElementsByTagName(tagname); el nombre de etiqueta debe ser comprador o vendedor, etc, ya que lo necesite. Itera sobre la lista de nodos y lee los datos.

1

¿Puedo preguntar por qué estás reinventando la rueda? Si está utilizando Java EE 6, ¿por qué no utilizar el mecanismo de seguridad integrado que es similar a lo que hace, pero de naturaleza declarativa?

Por favor, lea this article.

En esencia, se reducen a escribir esto en web.xml:

<security-constraint> 
    <display-name>For users in buyer role</display-name> 
    <web-resource-collection> 
     <web-resource-name>Restricted Access - Buyers Only</web-resource-name> 
     <url-pattern>buyoffer.xhtml</url-pattern> 
     <url-pattern>faq.xhtml</url-pattern> 
     <url-pattern>index.jsp</url-pattern> 
     <url-pattern>login.xhtml</url-pattern> 
     <url-pattern>main.xhtml</url-pattern> 
     <url-pattern>registrationSucceded.xhtml</url-pattern> 
     <http-method>GET</http-method> 
    </web-resource-collection> 
    <auth-constraint> 
     <role-name>Buyer</role-name> 
    </auth-constraint> 
    <user-data-constraint> 
     <transport-guarantee>NONE</transport-guarantee> 
    </user-data-constraint> 
</security-constraint> 

El ejemplo de arriba es para el rol de comprador.

+0

¿Cómo controlas la redirección aquí? – sfrj

+0

Eso es correcto. Encontré que la autenticación basada en filtro solo se ajusta a fines muy sofisticados. Por ejemplo, desea tener la posibilidad de otorgar algunos derechos por algún tiempo a algunos usuarios. Y desea recordar en db todas estas "subvenciones". Para casos comunes, la seguridad basada en contenedores es suficiente y efectiva. – Zbyszek

Cuestiones relacionadas