2012-04-02 3 views
0

Ich habe ein Problem beim Erstellen von benutzerdefinierten Security-Filter. Ich beabsichtige, einen Filter zu erstellen, der mit dem Server die Session-ID überprüfen würde, die in der URL übergeben wird - zur Authentifizierung & Autorisierung. Ich beabsichtige, das vorhandene JSF-Framework bereits im Code zu verwenden (wie Caching für Sitzungen usw.)JSF Erstellen einer verwalteten Bean (Anwendungsbereich) für die Sicherheitsverwaltung

Dafür definiere ich zuerst eine Bean, die Anwendungsbereich ist. Die Gesichter-config.xml sieht aus wie:

< Managed-Bean eifrig = "true" >
< Managed-Bean-Name > securityBean </managed-bean-name > < Managed-Bean-Klasse > com .ecom.scareer.security.SecurityBean </Managed-Bean-Klasse > < Managed-Bean-scope > Anwendung </Managed-Bean-scope >
< Managed-Eigenschaft < Eigenschaftsname loginBD </property-name > <Wert> # {loginBD} </Wert > </managed-property >
</managed-bean >

und dann eine Klasse definieren aufgerufen SecurityBean als:

public class SecurityBean implements Serializable { 


// attributes 
private LoginBD loginBD;  

public void setLoginBD(LoginBD loginBD) { 
this.loginBD = loginBD; 
} 


public UserSession getUserSessionById(String sessionId) throws InvalidSessionException{    

// get the session id 
UserSession us = loginBD.getSession(sessionId); 

return us; 
} 

} 

und ich habe einen Filter wie:

public class SecurityFilter implements Filter{ 

private ServletContext servletContext; 

// --------------- overridden method for Filter interface --------------- 

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

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

    Map<String, String[]> paramMap = request.getParameterMap(); 

    FacesContext facesContext = getFacesContext(request, response); 

    // get the application bean for security   
    SecurityBean sb = (SecurityBean)getApplicationBean("securityBean", facesContext); 

    // values needed from the parameter 
    String[] vals = paramMap.get("accountId"); 
    String accId = (vals != null && vals.length > 0)? vals[0] : null; 
    System.out.println("Account id .................. = " + accId); 

    String[] sessionIds = paramMap.get("sessionId"); 
    String sessionId = (sessionIds != null && sessionIds.length > 0)? sessionIds[0] : null; 

    System.out.println("The session ...................... = " + sessionId); 

    try { 

     UserSession us = sb.getUserSessionById(sessionId); 
    } catch (InvalidSessionException e) { 
     System.out.println("Invalid session exception "); 
     e.printStackTrace(); 
    } 

    chain.doFilter(request, response);    
} 

public void destroy() { 
    // do nothing  
} 


// --------------- for fetching the FacesContext 


// You need an inner class to be able to call FacesContext.setCurrentInstance 
// since it's a protected method 
private abstract static class InnerFacesContext extends FacesContext { 
    protected static void setFacesContextAsCurrentInstance(FacesContext facesContext) { 
     FacesContext.setCurrentInstance(facesContext); 
    } 
} 


private FacesContext getFacesContext(ServletRequest request, ServletResponse response) { 
    // Try to get it first 
    FacesContext facesContext = FacesContext.getCurrentInstance(); 
    if (facesContext != null) return facesContext; 

    FacesContextFactory contextFactory = (FacesContextFactory)FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY); 
    LifecycleFactory lifecycleFactory = (LifecycleFactory)FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);  
    Lifecycle lifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE); 

    // Either set a private member servletContext = filterConfig.getServletContext(); 
    // in you filter init() method or set it here like this: 
    // ServletContext servletContext = ((HttpServletRequest)request).getSession().getServletContext(); 
    // Note that the above line would fail if you are using any other protocol than http 

    // Doesn't set this instance as the current instance of FacesContext.getCurrentInstance 
    facesContext = contextFactory.getFacesContext(servletContext, request, response, lifecycle); 

    // Set using our inner class 
    InnerFacesContext.setFacesContextAsCurrentInstance(facesContext); 

    // set a new viewRoot, otherwise context.getViewRoot returns null 
    UIViewRoot view = facesContext.getApplication().getViewHandler().createView(facesContext, "yourOwnID"); 
    facesContext.setViewRoot(view); 

    return facesContext; 
} 


/** 
* 
* The method fetches the application bean for the given bean name. 
* The object returned should be cast correctly to the bean 
* 
* @param beanName - the name of bean as described in JSF config 
* @return - The bean as object. It should be cast to correct bean object before using 
*/  
private Object getApplicationBean(String beanName, FacesContext fContext) {  
    Object bean = fContext.getExternalContext().getApplicationMap().get(beanName);  
    return bean; 
} 
} 

Nun, wenn ich diese laufen bekomme ich folgende Probleme in meinem Server:

SEVERE: Critical error during deployment: 
com.sun.faces.mgbean.ManagedBeanCreationException: Unable to set property loginBD for managed bean securityBean 
at com.sun.faces.mgbean.ManagedBeanBuilder$BakedBeanProperty.set(ManagedBeanBuilder.java:615) 
at com.sun.faces.mgbean.ManagedBeanBuilder.buildBean(ManagedBeanBuilder.java:133) 
at com.sun.faces.mgbean.BeanBuilder.build(BeanBuilder.java:104) 
at com.sun.faces.mgbean.BeanManager.createAndPush(BeanManager.java:409) 
at com.sun.faces.mgbean.BeanManager.create(BeanManager.java:269) 
at com.sun.faces.mgbean.BeanManager.create(BeanManager.java:256) 
at com.sun.faces.config.ConfigureListener.contextInitialized(ConfigureListener.java:255) 
at org.apache.catalina.core.StandardContext.contextListenerStart(StandardContext.java:4690) 
at com.sun.enterprise.web.WebModule.contextListenerStart(WebModule.java:534) 
at org.apache.catalina.core.StandardContext.start(StandardContext.java:5305) 
at com.sun.enterprise.web.WebModule.start(WebModule.java:500) 
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:917) 
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:901) 
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:755) 
at com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:1980) 
at com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:1630) 
at com.sun.enterprise.web.WebApplication.start(WebApplication.java:100) 
at org.glassfish.internal.data.EngineRef.start(EngineRef.java:130) 
at org.glassfish.internal.data.ModuleInfo.start(ModuleInfo.java:269) 
at org.glassfish.internal.data.ApplicationInfo.start(ApplicationInfo.java:286) 
at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:461) 
at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:240) 
at org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:370) 
at com.sun.enterprise.v3.admin.CommandRunnerImpl$1.execute(CommandRunnerImpl.java:355) 
at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:370) 
at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1067) 
at com.sun.enterprise.v3.admin.CommandRunnerImpl.access$1200(CommandRunnerImpl.java:96) 
at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1247) 
at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1235) 
at com.sun.enterprise.v3.admin.AdminAdapter.doCommand(AdminAdapter.java:465) 
at com.sun.enterprise.v3.admin.AdminAdapter.service(AdminAdapter.java:222) 
at com.sun.grizzly.tcp.http11.GrizzlyAdapter.service(GrizzlyAdapter.java:168) 
at com.sun.enterprise.v3.server.HK2Dispatcher.dispath(HK2Dispatcher.java:117) 
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:234) 
at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:822) 
at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:719) 
at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1013) 
at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225) 
at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137) 
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104) 
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90) 
at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79) 
at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54) 
at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59) 
at com.sun.grizzly.ContextTask.run(ContextTask.java:71) 
at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532) 
at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513) 
at java.lang.Thread.run(Thread.java:619) 
Caused by: java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered? 
at org.springframework.web.jsf.FacesContextUtils.getRequiredWebApplicationContext(FacesContextUtils.java:83) 
at org.springframework.web.jsf.el.SpringBeanFacesELResolver.getWebApplicationContext(SpringBeanFacesELResolver.java:91) 
at org.springframework.web.jsf.el.SpringBeanFacesELResolver.getBeanFactory(SpringBeanFacesELResolver.java:79) 
at org.springframework.beans.factory.access.el.SpringBeanELResolver.getValue(SpringBeanELResolver.java:50) 
at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176) 
at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203) 
at com.sun.el.parser.AstIdentifier.getValue(AstIdentifier.java:99) 
at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:219) 
at com.sun.faces.mgbean.BeanBuilder$Expression.evaluate(BeanBuilder.java:591) 
at com.sun.faces.mgbean.ManagedBeanBuilder$BakedBeanProperty.set(ManagedBeanBuilder.java:606) 
... 47 more 

Wie kann ich einen Griff in der loginBD Eigenschaft (definiert in Flächen-config als Eigenschaft) erhalten? Gibt es eine Möglichkeit, diese Eigenschaft manuell (durch Code) zu injizieren? oder einen anderen Weg, um einen Griff zu bekommen?

Antwort

2

Dies ist nicht der richtige Weg, um eine beanspruchte Bean in einem Servlets zu erhalten. Sie müssen nicht manuell eine ganze FacesContext dafür erstellen. Verwaltete Beans im Anwendungsbereich werden als servletcontext-Attribute mit dem Namen des verwalteten Beans als Schlüssel gespeichert.

Also, in Ihrem doFilter() Methode, tun gerade:

ServletContext context = request.getServletContext(); 
SecurityBean securityBean = (SecurityBean) context.getAttribute("securityBean"); 
// ... 

In Bezug auf Ihr konkretes Problem, Sie scheinen diese Bohne zu müssen vor JSF jemals zum ersten Mal initialisiert erhalten. In diesem Fall müssen Sie es wirklich selbst erstellen, wenn es null ist.

if (securityBean == null) { 
    securityBean = new SecurityBean(); 
    securityBean.setLoginBD(new LoginBD()); // Or get it from application scope? 
    context.setAttribute("securityBean", securityBean); 
} 

// ... 

Unrelated auf das konkrete Problem, habe ich eine Menge Fragezeichen, um diesen Design-Ansatz.Aber da die konkrete funktionale Anforderung unklar ist, kann ich nicht den richtigen Ansatz vorschlagen. Mindestens scheint neu zu erfinden, was bereits von Container-verwaltete Authentifizierung und/oder HttpSession, Session-Bereich verwaltete Beans, EJBs, etc. Das ist nicht richtig. Dies ist unnötig kompliziert.

+0

Hallo Balus, danke für eine schnelle Antwort. Wir erstellen Session-IDs und speichern sie im Cache (sowie in der Datenbank), wenn sich ein Benutzer mit anderen Benutzerinformationen anmeldet. Wenn der Benutzer nun zu den Seiten navigiert, haben alle Links die sessionId in der URL, die sowohl auf Ablaufdatum als auch auf Autorisierung überprüft wird. Ich beabsichtige, den vorhandenen Sitzungscache zu verwenden (auf den von der loginBD zugegriffen wird), der eine Spring-Komponente ist. Mein Problem ist, wenn ich diese Bean als Anwendungsbereich und eifrig = wahr mache, dann kann ich nicht den Griff zu loginBD bekommen. Ich habe den Code gemäß Ihrem Vorschlag korrigiert. – Gaurav

+0

Zusätzlich zu den obigen.Ich habe die Zeile securityBean.setLoginBD (new LoginBD()) hinzugefügt; nach Ihrem Kommentar. Aber die loginBD selbst verwendet AutoWiring und Spring-Annotationen, um die Dao-Werte zu erhalten. Daher geben sie später innerhalb der loginBD Nullzeiger. Gibt es sowieso eine Verzögerung der Initialisierung der Application-Scope-Bean, bis die Spring-Komponenten geladen sind? Ich benutze Glassfish Server. – Gaurav

Verwandte Themen