2012-04-10 47 views
0

我在JSF 2.0中創建了一個自定義組件。其目的是在輸入文本框中顯示會話屬性值。我想要在HttpSessionListener sessionCreated方法中創建會話屬性。問題是encodeAll方法在sessionCreated方法之前被調用。在encodeAll之前調用sessionCreated應該怎麼做?在sessionCreated()之前調用的JSF 2.0 encodeAll()

的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

設置會話ID,純粹是示範性的,我承擔?你有什麼具體問題?你是否在'session.getAttribute()'行上得到了'NullPointerException'?還是你得到了一個你在那裏編碼的'RuntimeException'? – BalusC 2012-04-12 21:10:29

+0

由於'session'對象爲空,我得到'NullPointerException'。這意味着即使在會話創建之前,encodeAll方法也會執行嗎?無論如何,我的實際目標是創建一個隨機數並將其放在會話範圍內以防止CSRF。 JSF 1.2中的類似代碼在'encodeBegin'之前調用'sessionCreated',所以我沒有這個問題。 – Praneeth 2012-04-13 13:44:05

+0

你應該在問題中更清楚。我已經猜到了,但你對此沒有明確表態。例外情況不應該被忽視,就好像它們是裝飾一樣。我發佈了一個答案。 – BalusC 2012-04-13 14:01:20

回答

0

通過getSession(true)更換getSession(false)

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

該布爾值指示當尚未創建會話時是否創建會話。由於getSession(false)因此當您尚未在此時創建null時有風險,因此無論您何時調用其中的任何方法,您都有可能獲得。另見javadoc


無關的具體問題,清潔劑是使用ExternalContext#getSessionMap()代替。在您的JSF代碼中導入「raw」javax.servlet通常表示JSF代碼中有異味。即有些事情已經不必要地過度完成了。然後,您應該使用純粹的JSF API尋找更簡單的方法。

更換

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

通過

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

太棒了!我想用'getSession(true)'替換'getSession(false)'',但不確定它是否適合我的CSRF。我不認爲我可以使用'ExternalContext#getSessionMap()'作爲'sessionId'將始終爲'null' – Praneeth 2012-04-13 14:56:33

+0

這將是JSF impl中使用的一個主要錯誤。如果你這樣設置,它肯定不應該是'null'。您使用的是JSF impl/version? – BalusC 2012-04-13 15:02:40

+0

Mojarra 2.1.3(FCS b02) – Praneeth 2012-04-13 15:18:52