2011-01-20 13 views
15

Come si eseguono il rendering dei componenti JSF in base al ruolo dell'utente connesso? So che il contesto esterno espone i principal, ma come dovrei eseguire correttamente il rendering in JSF? In JSP sarebbe qualcosa di simile aRendere il componente JSF in base al ruolo utente

<% isUserInRole(Roles.ADMIN) { %> 
<button>Edit!</button> 
<% } %> 

Come posso scrivere questo in JSF nel miglior modo possibile? La mia ipotesi migliore è l'attributo reso legato al metodo di un backing bean che restituisce un booleano, ma che introdurrebbe un bean backing irrilevante se devo rendere alcuni elementi di navigazione solo per gli amministratori ...

Glassfish V3.1, JSF 2.x

+1

JSF 1.xo 2.x? – BalusC

+0

2.x, Glassfish 3.1 – TC1

+0

In futuro, si prega di aggiungere il tag '[jsf-2.0]' per indicare che :) – BalusC

risposta

31

Se il web.xml è dichiarato come Servlet 3.0 (che si riferisce implicitamente alla JSP/EL 2,2)

<?xml version="1.0" encoding="UTF-8"?> 
<web-app 
    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-app_3_0.xsd" 
    version="3.0"> 

allora si può prendere vantaggio di essere in grado di richiamare i metodi con argomenti in EL come come ExternalContext#isUserInRole():

rendered="#{facesContext.externalContext.isUserInRole('ADMIN')}" 

Si noti che questo richiede un contenitore abilitato per Servlet 3.0, ma poiché si utilizza Glassfish 3 (che supporta Servlet 3.0), dovrebbe funzionare senza problemi.

Si noti inoltre che se si sta utilizzando Facelets invece di JSP, allora hai la disposizione HttpServletRequest come #{request} in EL, che consente la seguente espressione più breve:

rendered="#{request.isUserInRole('ADMIN')}" 
+0

È davvero Servlet 3.0, ma in qualche modo tra tutte quelle storie della sessione d'esame che avevo dimenticato hanno aggiunto chiamate di metodo a JSF ... Grazie mille :) – TC1

+1

Non è specificamente JSF, è EL (quelli '# {}' cose) che conta. Se si esegue JSF 2.0 ad esempio su Servlet 2.5 (che implica JSP/EL 2.1), non funzionerà. È stato introdotto in JSP/EL 2.2. – BalusC

+0

Ho definito i ruoli per ciascun utente utilizzando JDBC Realm. Ma l'espressione sopra riportata restituisce sempre "false" per qualsiasi utente. Devo aggiungere qualche altra cosa per farlo funzionare? – wasimbhalli

0

Memorizza il ruolo nell'attributo di sessione e confronta solo quello utilizzando l'attributo reso.

ad es. rendered="#{yoursessionbean.userRole == Roles.ADMIN}"

+0

Questa era una delle mie idee all'inizio, ma l'utente può avere un numero infinito di ruoli basati sul suo gruppi. Funzionerebbe davvero solo se l'utente avesse un solo ruolo ... – TC1

+0

@ TC1 - d'accordo, quindi dovrai fare una chiamata al metodo o aspettare se arriva un'altra soluzione. – niksvp

5

In risposta a @wasimbhalli, ci sono due ragioni che ho trovato che l'espressione avrebbe sempre return false:

  1. Il nome del ruolo è case sensitive. rendered="#{facesContext.externalContext.isUserInRole('ADMIN')}" può restituire false, ma provare rendered="#{facesContext.externalContext.isUserInRole('admin')}" o render = "# {facesContext.externalContext.isUserInRole ('Admin')}".

  2. È necessario definire i ruoli in entrambi web.xml (o come annotazioni) e mapparlo in glassfish-web.xml.

Il seguente è come specificare un ruolo nella web.ml

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns="http://java.sun.com/xml/ns/javaee" 
     xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> 
    <security-role> 
    <role-name>admin</role-name> 
    </security-role> 
</web-app> 

Il seguente è come mappare il gruppo di autenticazione per il ruolo in glassfish-web.xml.

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd"> 
<glassfish-web-app> 
    <security-role-mapping> 
    <role-name>admin</role-name> <!-- name defined in web.xml or annotations --> 
    <group-name>admin</group-name><!-- name from authentication mechanism --> 
    </security-role-mapping> 
</glassfish-web-app> 

Nel mio test è stato necessario per fare la mappatura anche quando i nomi erano gli stessi, come mostro nel mio codice di esempio. Anche nei miei test, ho provato a definire solo la mappatura e solo a definire il ruolo in web.xml e nessuno dei due ha funzionato. Avevo bisogno di entrambi, come specificando il nome del ruolo nel caso corretto.

Problemi correlati