2012-12-21 24 views
5

In meiner JSF-Anwendung gibt es eine Filter, die verwendet wird, um den authentischen Prozess zu überprüfen. Wenn die Authentifizierung fehlschlägt, wird der Filter an login.xhtml umgeleitet. Wie kann ich die FacesMessage von Filter an meine Login-Seite übergeben?Set FacesMessage von Filter

Obwohl ich unten verwendet, ist es nicht OK.

FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, message, null)); 

AuthenticationFilter.java

public class AuthenticationFilter implements Filter { 
    private FilterConfig config; 
    private ServletContext servletContext; 

    public void init(FilterConfig filterConfig) { 
     config = filterConfig; 
     servletContext = config.getServletContext(); 
    } 

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 
     HttpServletRequest httpRequest = (HttpServletRequest) servletRequest; 
     HttpServletResponse httpResponse = (HttpServletResponse) servletResponse; 
     HttpSession session = httpRequest.getSession(); 
     User user = (User) session.getAttribute(Constants.LOGIN_USER); 
     if (user == null) { 
      ... 
      FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, message, null)); 

      String loginView = httpRequest.getContextPath() + Constants.LOGIN_PAGE; 
      httpResponse.sendRedirect(loginView); 
     } else if (!user.getRole().equals(Role.SYSTEM_ADMINISTRATOR)) { 
      .... 
      FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, message, null)); 

      String loginView = httpRequest.getContextPath() + Constants.LOGIN_PAGE; 
      httpResponse.sendRedirect(loginView); 
     } else { 
      filterChain.doFilter(servletRequest, servletResponse); 
     } 
     servletContext.log("Exiting the filter"); 
    } 

    public void destroy() { 
     //Nothing to do. 
    } 
} 

Antwort

7

Die FacesContext vom FacesServlet erstellt wird. Wenn Sie sich in einem Filter befinden, wurde er noch nicht aufgerufen. Filter werden vor Servlets ausgeführt. So können Sie in einem Filter nie die Hand zum FacesContext bekommen. Außerdem sind Gesichter-Nachrichten im Bereich der Anfrage, so dass eine Umleitung sie sowieso zum Verschwinden gebracht hätte.

Lassen Sie die login.xhtml selbst während einer <f:event type="preRenderView"> setzen. Der einfachste Weg wäre, den Filter vorübergehend in den Sitzungsumfang zu setzen.

session.setAttribute("message", message); 
httpResponse.sendRedirect(loginView); 

, die Sie dann in dem Sitzungsbereich entfernen Pre Ansicht Listener-Methode von login.xhtml machen:

String message = (String) externalContext.getSessionMap().remove("message"); 

if (message != null) { 
    context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, message, null)); 
} 
+0

danke für Ihre Unterstützung. – CycDemo

+0

Gern geschehen. – BalusC

0

ich in ein ähnliches Problem liefen mit dem Versuch, den Faces in einem EJB-Timer zu erhalten. BalusC hat auf mehrere Threads hingewiesen, dass dies unmöglich ist. Alternativ können Sie einen 'ServletContextListener' verwenden, aber der ScheduledExecutorService definiert die Planung nicht so gut wie einen EJB-Timer.

In jedem Fall bestand ein Vorschlag darin, eine Webanforderung an eine JSF-Seite zu senden, die von einer verwalteten Bean unterstützt wurde, um die Methoden der Anwendungsbereichs-Bean zu verwenden, die ich mit einem Timer einrichten wollte.

Ich erwähne dies, weil es scheint, als könnten Sie etwas Ähnliches tun, wo Sie einen Parameter an die JSF-Seite mit der gewünschten Nachricht und die Benutzer-IP-Adresse oder etwas übergeben. Diese Seite könnte von einer Anfrage-Bean im Bean-Bereich unterstützt werden, in die eine Anwendungsbereichs-Bean injiziert wurde, die diese in einer Karte mit der IP als Schlüssel speichert. Wenn der Benutzer dann auf die Anmeldeseite umgeleitet wird, könnte diese Seite eine get error message-Methode für eine Anfrage-Bean aufrufen, in die dieselbe Anwendungsbereichs-Bean injiziert wird, die die Fehlermeldung für diese IP oder etwas in dieser Richtung erhält.

In jedem Fall bin ich mir sicher, dass die Antwort von BalusC ausreichend und korrekter ist, aber sein Vorschlag "nur eine Anfrage vom ejb-Timer machen" funktionierte gut für die Terminierung von Methodenaufrufen auf Anwendungsbereichs-Beans und ich Ich dachte, ich könnte seinen möglichen Gebrauch hier erwähnen.

@BalusC Haben Sie eine Idee über den Post, auf den ich mich beziehe? Ich kann es nicht finden.