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?
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
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