2012-04-10 5 views
0

Ich habe eine benutzerdefinierte Komponente in JSF 2.0 erstellt. Sein Zweck besteht darin, einen Sitzungsattributwert in einem Eingabetextfeld anzuzeigen. Ich möchte das Session-Attribut in HttpSessionListener sessionCreated Methode erstellt werden. Das Problem ist encodeAll Methode wird vor sessionCreated Methode aufgerufen. Was sollte ich tun, um sessionCreated vor encodeAll aufgerufen zu machen?JSF 2.0 encodeAll() aufgerufen vor sessionCreated()

web.xml

<context-param> 
    <param-name>javax.faces.FACELETS_LIBRARIES</param-name> 
    <param-value>/WEB-INF/components.taglib.xml</param-value> 
</context-param> 
<listener> 
    <listener-class>mycomp.jsf.listener.MyListener</listener-class> 
</listener> 

components.taglib.xml

<facelet-taglib 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-facelettaglibrary_2_0.xsd" 
      version="2.0"> 
<namespace>http://mycomp/jsf/components</namespace> 
<tag> 
    <tag-name>mycomp</tag-name> 
    <component> 
     <component-type>MyComp</component-type> 
    </component> 
</tag> 
</facelet-taglib> 

MyListener.java

public class MyListener implements HttpSessionListener { 
@Override 
public void sessionCreated(HttpSessionEvent event) { 
    HttpSession session = event.getSession(); 
    session.setAttribute("sessionid", session.getId()); 
} 
@Override 
public void sessionDestroyed(HttpSessionEvent se) { 
} 
} 

MyComp.java

@FacesComponent(value = "MyComp") 
public class MyComp extends UIComponentBase { 
public MyComp() { 
    setRendererType(null); 
} 
protected Class getComponentClass() { 
    return this.getClass(); 
} 
@Override 
public void decode(FacesContext context) { 
//some logic 
} 
@Override 
public void encodeAll(FacesContext context) throws IOException { 
    String clientId = getClientId(context) + ":token"; 
    HttpSession session = (HttpSession) context.getExternalContext().getSession(false); 
    String sessionId = (String) session.getAttribute("sessionid"); 
    if (sessionId == null || "".equals(sessionId)) { 
     throw new RuntimeException("sessionid is missing!"); 
    } 
    ResponseWriter writer = context.getResponseWriter(); 
    writer.startElement("input", this); 
    writer.writeAttribute("type", "text", "type"); 
    writer.writeAttribute("name", clientId, "name"); 
    writer.writeAttribute("value", sessionId, "value"); 
    writer.endElement("input"); 
} 
@Override 
public String getFamily() { 
    return null; 
} 
} 

index.xhtml

<html xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:h="http://java.sun.com/jsf/html" 
    xmlns:t="http://mycomp/jsf/components"> 
<h:head> 
</h:head> 
<h:body> 
    <h:form> 
     <t:mycomp /> 
    </h:form> 
</h:body> 
</html> 
+0

die Session-ID Einstellung rein beispielhaft ist, nehme ich an? Was ist dein konkretes Problem? Haben Sie eine 'NullPointerException' in der Zeile' session.getAttribute() 'bekommen? Oder hast du eine 'RuntimeException' bekommen, die du selbst dort codiert hast? – BalusC

+0

Ich bekomme eine "NullPointerException", da das 'session'-Objekt null ist. Bedeutet das, dass die Methode 'encodeAll' ausgeführt wird, noch bevor die Sitzung erstellt wurde? Wie auch immer, mein eigentliches Ziel ist es, eine Zufallszahl zu erstellen und sie in den Sitzungsumfang zu setzen, um CSRF zu verhindern. Ähnlicher Code in JSF 1.2 hatte 'sessionCreated' vor 'encodeBegin' aufgerufen, daher hatte ich dieses Problem nicht. – Praneeth

+0

Sie hätten darüber in der Frage klarer sein sollen. Das habe ich schon vermutet, aber Sie haben das nicht ausdrücklich erwähnt. Ausnahmen sollten nicht ignoriert werden, als wären sie Dekoration. Ich habe eine Antwort geschrieben. – BalusC

Antwort

0

ersetzen getSession(false) durch getSession(true).

HttpSession session = (HttpSession) context.getExternalContext().getSession(true); 

Der boolesche Wert gibt an, ob die Sitzung erstellt werden soll oder nicht, wenn sie noch nicht erstellt wurde. Mit getSession(false) riskierst du also, eine null zu bekommen, wenn es noch nicht zu diesem Zeitpunkt erstellt wurde und daher die NullPointerException, wenn Sie irgendwelche Methoden darauf aufrufen. Siehe auch die javadoc.


Unrelated auf das konkrete Problem, ist sauberer ExternalContext#getSessionMap() stattdessen zu verwenden. Wenn Sie "rohe" javax.servlet Importe in Ihren JSF-Code importieren, werden normalerweise Gerüche im JSF-Code angezeigt. I.e. etwas wurde unnötigerweise zu kompliziert gemacht. Sie sollten dann nach einfacheren Wegen mit der reinen JSF-API suchen.

ersetzen

HttpSession session = (HttpSession) context.getExternalContext().getSession(true); 
String sessionId = (String) session.getAttribute("sessionid"); 
if (sessionId == null || "".equals(sessionId)) { 
    throw new RuntimeException("sessionid is missing!"); 
} 

von

String sessionId = (String) context.getExternalContext().getSessionMap().get("sessionid"); 
if (sessionId == null || "".equals(sessionId)) { 
    throw new RuntimeException("sessionid is missing!"); 
} 
+0

Großartig !!! Ich dachte daran, 'getSession (false)' durch 'getSession (true)' zu ersetzen, war mir aber nicht sicher, ob es in meine CSRF passt. Ich glaube nicht, dass ich 'ExternalContext # getSessionMap()' verwenden kann, da 'sessionId' immer 'null' ist. – Praneeth

+0

Das wäre ein großer Fehler in JSF impl. Es sollte sicherlich nicht "null" sein, wenn Sie es so einstellen. Welche JSF-Version verwenden Sie? – BalusC

+0

Mojarra 2.1.3 (FCS b02) – Praneeth

Verwandte Themen