{"id":31,"date":"2007-08-18T21:02:00","date_gmt":"2007-08-18T21:02:00","guid":{"rendered":"http:\/\/euve3303.vserver.de\/stefan\/blog\/?p=33"},"modified":"2011-12-02T21:53:50","modified_gmt":"2011-12-02T20:53:50","slug":"security-fur-jsf-komponenten-mit-spring-aop","status":"publish","type":"post","link":"https:\/\/cogito-ergo-blog.de\/blog\/2007\/08\/18\/security-fur-jsf-komponenten-mit-spring-aop\/","title":{"rendered":"Security f\u00fcr JSF-Komponenten mit Spring AOP"},"content":{"rendered":"<p>[:de]<\/p>\n<h3>Spring als Factory f\u00fcr JSF-Components<\/h3>\n<p>Wie schon im letzten <a href=\"\/blog\/?p=30\">Beitrag &#8220;JSF-Components mit Spring und Velocity-Templates&#8221;<\/a> soll auch bei diesem Beispiel Spring zum Erzeugen von JSF-Componenten benutzt werden.<\/p>\n<p>Noch einmal kurz das Vorgehen: in der faces-config.xml wird mit:<\/p>\n<pre class=\"brush: xml; class-name: code; title: ; notranslate\" title=\"\">\r\n&lt;factory&gt;\r\n    &lt;application-factory&gt;\r\n      org.springframework.web.jsf.SpringApplicationFactory\r\n    &lt;\/application-factory&gt;\r\n&lt;\/factory&gt;\r\n<\/pre>\n<p>eine ApplicationFactory eingetragen, die Spring ins Spiel bringt, um JSF-Components zu erzeugen. Im letzten Artikel hatte ich das benutzt, um Komponenten wie SpringBeans zu erzeugen und zu konfigurieren.<\/p>\n<p>Wenn Spring die Komponenten erzeugt, dann lassen sich alle Spring Features voll zum Einsatz bringen, unter anderem auch AOP:<\/p>\n<p>Man kann z.B. abh\u00e4ngig von der ROLE eines User eine Komponente anzeigen oder nicht. Hierzu schreibt man einen MethodInterceptor, der die Aufrufe der &#8220;encode*&#8221;-Calls auf die Komponente \u00fcberpr\u00fcft. Die SpringApplication kann aber noch mehr. AOP l\u00e4\u00dft sich n\u00e4mlich auch auf die Standard-Komponenten anwenden &#8230;<\/p>\n<p><!--more--><\/p>\n<h3>Spring ProxyFactory zum Wrappen der Standard-Komponenten<\/h3>\n<p>Hinter den Kulissen nutzt Spring f\u00fcr AOP die ProxyFactory zum Erzeugen von &#8220;Advised&#8221;-Objects. Genau diesen Mechanismus kann man auch auf alle Standard-JSF-Components anwenden. Die entsprechende Methode in der SpringApplication sieht dann so aus:<\/p>\n<pre class=\"brush: java; class-name: code; title: ; notranslate\" title=\"\">\r\n    \/**\r\n     * Tries to create a UI component via the original Application and looks for\r\n     * the UI component in Spring's root application context if it is not\r\n     * obtainable through JSF's Application.\r\n     * @param componentType the component type and Spring bean name for the UIComponent\r\n     * @return the resulting UIComponent\r\n     *         through either the JSF Application or Spring Application Context.\r\n     * @throws FacesException if the component could not be created or located in Spring\r\n     *\/\r\n    public UIComponent createComponent(String componentType) throws FacesException {\r\n        FacesException originalException = null;\r\n        try {\r\n            \/\/ Get component from Spring root context\r\n            if (logger.isDebugEnabled()) {\r\n                logger.debug(&quot;Attempting to find component '&quot; + componentType + &quot;' in root WebApplicationContext&quot;);\r\n            }\r\n            FacesContext facesContext = FacesContext.getCurrentInstance();\r\n            if( facesContext != null ) {\r\n              WebApplicationContext wac = getWebApplicationContext(facesContext);\r\n              if (wac.containsBean(componentType)) {\r\n                  if (logger.isDebugEnabled()) {\r\n                      logger.debug(&quot;Successfully found component '&quot; + componentType + &quot;' in root WebApplicationContext&quot;);\r\n                  }\r\n                  return (UIComponent) wac.getBean(componentType);\r\n              }\r\n            }\r\n\r\n            \/\/ Create component with original application\r\n            if (logger.isDebugEnabled()) {\r\n                logger.debug(&quot;Attempting to create component with type '&quot; + componentType + &quot;' using original Application&quot;);\r\n            }\r\n            UIComponent originalComponent = this.originalApplication.createComponent(componentType);\r\n            if (originalComponent != null) {\r\n              try {\r\n                System.out.println(&quot;trying to proxy &quot; + originalComponent);\r\n                ProxyFactory fac = new ProxyFactory(originalComponent);\r\n                fac.addAdvice(new RenderMethodInterceptor());\r\n                \/\/fac.addAdvisor(new TestAdvisor());\r\n                fac.setProxyTargetClass(true);\r\n                return (UIComponent) fac.getProxy();\r\n              } catch( org.springframework.aop.framework.AopConfigException e) {\r\n                System.out.println(&quot;could not proxy comp type: &quot;+ componentType);\r\n                return originalComponent;\r\n              }\r\n            }\r\n            originalException = new FacesException(&quot;Original Application returned a null component&quot;);\r\n        } catch (FacesException e) {\r\n            originalException = e;\r\n        }\r\n\r\n        if (logger.isDebugEnabled()) {\r\n            logger.debug(&quot;Could not create component '&quot; + componentType + &quot;'&quot;);\r\n        }\r\n        throw new FacesException(&quot;Could not create component using original Application.  &quot; +\r\n                                 &quot;Also, could not find component in root WebApplicationContext&quot;, originalException);\r\n    }\r\n\r\n<\/pre>\n<p>Auf diese Weise l\u00e4\u00dft sich nun das Rendering auch aller Standard-Komponenten \u00fcber den MethodInterceptor steuern. Man kann so z.B. mit Acegi oder Standard-Security-Mechanismen des WebContainers die Anzeige (oder auch den Style der Komponenten steuern.<\/p>\n<p>F\u00fcr Acegi sieht der MethodInterceptor so aus:<\/p>\n<pre class=\"brush: java; class-name: code; title: ; notranslate\" title=\"\">\r\n    \/**\r\n     * Tries to create a UI component via the original Application and looks for\r\n     * the UI component in Spring's root application context if it is not\r\n     * obtainable through JSF's Application.\r\n     * @param componentType the component type and Spring bean name for the UIComponent\r\n     * @return the resulting UIComponent\r\n     *         through either the JSF Application or Spring Application Context.\r\n     * @throws FacesException if the component could not be created or located in Spring\r\n     *\/\r\n    public UIComponent createComponent(String componentType) throws FacesException {\r\n        FacesException originalException = null;\r\n        try {\r\n            \/\/ Get component from Spring root context\r\n            if (logger.isDebugEnabled()) {\r\n                logger.debug(&quot;Attempting to find component '&quot; + componentType + &quot;' in root WebApplicationContext&quot;);\r\n            }\r\n            FacesContext facesContext = FacesContext.getCurrentInstance();\r\n            if( facesContext != null ) {\r\n              WebApplicationContext wac = getWebApplicationContext(facesContext);\r\n              if (wac.containsBean(componentType)) {\r\n                  if (logger.isDebugEnabled()) {\r\n                      logger.debug(&quot;Successfully found component '&quot; + componentType + &quot;' in root WebApplicationContext&quot;);\r\n                  }\r\n                  return (UIComponent) wac.getBean(componentType);\r\n              }\r\n            }\r\n\r\n            \/\/ Create component with original application\r\n            if (logger.isDebugEnabled()) {\r\n                logger.debug(&quot;Attempting to create component with type '&quot; + componentType + &quot;' using original Application&quot;);\r\n            }\r\n            UIComponent originalComponent = this.originalApplication.createComponent(componentType);\r\n            if (originalComponent != null) {\r\n              try {\r\n                System.out.println(&quot;trying to proxy &quot; + originalComponent);\r\n                ProxyFactory fac = new ProxyFactory(originalComponent);\r\n                fac.addAdvice(new RenderMethodInterceptor());\r\n                \/\/fac.addAdvisor(new TestAdvisor());\r\n                fac.setProxyTargetClass(true);\r\n                return (UIComponent) fac.getProxy();\r\n              } catch( org.springframework.aop.framework.AopConfigException e) {\r\n                System.out.println(&quot;could not proxy comp type: &quot;+ componentType);\r\n                return originalComponent;\r\n              }\r\n            }\r\n            originalException = new FacesException(&quot;Original Application returned a null component&quot;);\r\n        } catch (FacesException e) {\r\n            originalException = e;\r\n        }\r\n\r\n        if (logger.isDebugEnabled()) {\r\n            logger.debug(&quot;Could not create component '&quot; + componentType + &quot;'&quot;);\r\n        }\r\n        throw new FacesException(&quot;Could not create component using original Application.  &quot; +\r\n                                 &quot;Also, could not find component in root WebApplicationContext&quot;, originalException);\r\n    }\r\n\r\n<\/pre>\n<h3>Facelets machens wiederum einfacher<\/h3>\n<p>Facelets erleichtern auch hier das Leben: man kann eine Komponente mit beliebigen Attributen &#8220;schm\u00fccken&#8221; ohne dass diese zuvor deklariert werden m\u00fcssen. Es gen\u00fcgt also ein <em>requiredRole=&#8217;admin&#8217;<\/em> in den Command-Button zu schreiben und schon wird er nur noch f\u00fcr Admins sichtbar.<\/p>\n<p>Kompletten Sourcecode gibt&#8217;s <a href=\"http:\/\/www.stefan-rinke.de\/download\/jsf-acegi.zip\">hier<\/a>.[\/:de][:en]<\/p>\n<h3>Spring as factory for JSF components<\/h3>\n<p>Like in the recent article <a href=\"\/blog\/?p=30\">&#8220;JSF components using Spring and Velocity templates&#8221;<\/a> I will use Spring to create JSF components in this example.<\/p>\n<p>Last time the approach works as follows: configure a factory in faces-config.xml like this:<\/p>\n<pre class=\"brush: xml; class-name: code; title: ; notranslate\" title=\"\">\r\n&lt;factory&gt;\r\n    &lt;application-factory&gt;\r\n      org.springframework.web.jsf.SpringApplicationFactory\r\n    &lt;\/application-factory&gt;\r\n&lt;\/factory&gt;\r\n<\/pre>\n<p>Using this ApplicationFactory enables spring to create jsf components. I used this factory last time to create and configure components like spring beans via the application context.<\/p>\n<p>But if spring creates components we could easily apply more spring features e.g. spring AOP:<\/p>\n<p>If you would like to display a component depending on the ROLE a user has, you could write a MethodInterceptor, that catches (and checks) all calls to the &#8220;encode*&#8221; methods of the component. And the SpringApplication class is even more useful. AOP can easily applied to all standard components &#8230;<\/p>\n<p><!--more--><\/p>\n<h3>Spring ProxyFactory to wrap the standard components<\/h3>\n<p>Under th hood spring uses the ProxyFactory to implement AOP features like creating advised objects. Exactly this mechanism can be applied to all standard jsf components (like outputText for instance). The corrosponding method in the SpringApplication class looks like this:<\/p>\n<pre class=\"brush: java; class-name: code; title: ; notranslate\" title=\"\">\r\n    \/**\r\n     * Tries to create a UI component via the original Application and looks for\r\n     * the UI component in Spring's root application context if it is not\r\n     * obtainable through JSF's Application.\r\n     * @param componentType the component type and Spring bean name for the UIComponent\r\n     * @return the resulting UIComponent\r\n     *         through either the JSF Application or Spring Application Context.\r\n     * @throws FacesException if the component could not be created or located in Spring\r\n     *\/\r\n    public UIComponent createComponent(String componentType) throws FacesException {\r\n        FacesException originalException = null;\r\n        try {\r\n            \/\/ Get component from Spring root context\r\n            if (logger.isDebugEnabled()) {\r\n                logger.debug(&quot;Attempting to find component '&quot; + componentType + &quot;' in root WebApplicationContext&quot;);\r\n            }\r\n            FacesContext facesContext = FacesContext.getCurrentInstance();\r\n            if( facesContext != null ) {\r\n              WebApplicationContext wac = getWebApplicationContext(facesContext);\r\n              if (wac.containsBean(componentType)) {\r\n                  if (logger.isDebugEnabled()) {\r\n                      logger.debug(&quot;Successfully found component '&quot; + componentType + &quot;' in root WebApplicationContext&quot;);\r\n                  }\r\n                  return (UIComponent) wac.getBean(componentType);\r\n              }\r\n            }\r\n\r\n            \/\/ Create component with original application\r\n            if (logger.isDebugEnabled()) {\r\n                logger.debug(&quot;Attempting to create component with type '&quot; + componentType + &quot;' using original Application&quot;);\r\n            }\r\n            UIComponent originalComponent = this.originalApplication.createComponent(componentType);\r\n            if (originalComponent != null) {\r\n              try {\r\n                System.out.println(&quot;trying to proxy &quot; + originalComponent);\r\n                ProxyFactory fac = new ProxyFactory(originalComponent);\r\n                fac.addAdvice(new RenderMethodInterceptor());\r\n                \/\/fac.addAdvisor(new TestAdvisor());\r\n                fac.setProxyTargetClass(true);\r\n                return (UIComponent) fac.getProxy();\r\n              } catch( org.springframework.aop.framework.AopConfigException e) {\r\n                System.out.println(&quot;could not proxy comp type: &quot;+ componentType);\r\n                return originalComponent;\r\n              }\r\n            }\r\n            originalException = new FacesException(&quot;Original Application returned a null component&quot;);\r\n        } catch (FacesException e) {\r\n            originalException = e;\r\n        }\r\n\r\n        if (logger.isDebugEnabled()) {\r\n            logger.debug(&quot;Could not create component '&quot; + componentType + &quot;'&quot;);\r\n        }\r\n        throw new FacesException(&quot;Could not create component using original Application.  &quot; +\r\n                                 &quot;Also, could not find component in root WebApplicationContext&quot;, originalException);\r\n    }\r\n\r\n<\/pre>\n<p>Doing it that way I can control the rendering of all standard jsf components via a MethodInterceptor as well. You can use Acegi or standard security mechanism provided by the j2ee container to control the visibility (possibly even the display style) of the components.<\/p>\n<p>Using Acegi the MethodInterceptor looks like this:<\/p>\n<pre class=\"brush: java; class-name: code; title: ; notranslate\" title=\"\">\r\n    \/**\r\n     * Tries to create a UI component via the original Application and looks for\r\n     * the UI component in Spring's root application context if it is not\r\n     * obtainable through JSF's Application.\r\n     * @param componentType the component type and Spring bean name for the UIComponent\r\n     * @return the resulting UIComponent\r\n     *         through either the JSF Application or Spring Application Context.\r\n     * @throws FacesException if the component could not be created or located in Spring\r\n     *\/\r\n    public UIComponent createComponent(String componentType) throws FacesException {\r\n        FacesException originalException = null;\r\n        try {\r\n            \/\/ Get component from Spring root context\r\n            if (logger.isDebugEnabled()) {\r\n                logger.debug(&quot;Attempting to find component '&quot; + componentType + &quot;' in root WebApplicationContext&quot;);\r\n            }\r\n            FacesContext facesContext = FacesContext.getCurrentInstance();\r\n            if( facesContext != null ) {\r\n              WebApplicationContext wac = getWebApplicationContext(facesContext);\r\n              if (wac.containsBean(componentType)) {\r\n                  if (logger.isDebugEnabled()) {\r\n                      logger.debug(&quot;Successfully found component '&quot; + componentType + &quot;' in root WebApplicationContext&quot;);\r\n                  }\r\n                  return (UIComponent) wac.getBean(componentType);\r\n              }\r\n            }\r\n\r\n            \/\/ Create component with original application\r\n            if (logger.isDebugEnabled()) {\r\n                logger.debug(&quot;Attempting to create component with type '&quot; + componentType + &quot;' using original Application&quot;);\r\n            }\r\n            UIComponent originalComponent = this.originalApplication.createComponent(componentType);\r\n            if (originalComponent != null) {\r\n              try {\r\n                System.out.println(&quot;trying to proxy &quot; + originalComponent);\r\n                ProxyFactory fac = new ProxyFactory(originalComponent);\r\n                fac.addAdvice(new RenderMethodInterceptor());\r\n                \/\/fac.addAdvisor(new TestAdvisor());\r\n                fac.setProxyTargetClass(true);\r\n                return (UIComponent) fac.getProxy();\r\n              } catch( org.springframework.aop.framework.AopConfigException e) {\r\n                System.out.println(&quot;could not proxy comp type: &quot;+ componentType);\r\n                return originalComponent;\r\n              }\r\n            }\r\n            originalException = new FacesException(&quot;Original Application returned a null component&quot;);\r\n        } catch (FacesException e) {\r\n            originalException = e;\r\n        }\r\n\r\n        if (logger.isDebugEnabled()) {\r\n            logger.debug(&quot;Could not create component '&quot; + componentType + &quot;'&quot;);\r\n        }\r\n        throw new FacesException(&quot;Could not create component using original Application.  &quot; +\r\n                                 &quot;Also, could not find component in root WebApplicationContext&quot;, originalException);\r\n    }\r\n\r\n<\/pre>\n<h3>Facelets make things easier<\/h3>\n<p>Facelets simplifies your life: we could attach arbitrary attribute to a component without to need to declare them before. To put a simple <em>requiredRole=&#8217;admin&#8217;<\/em> into the commandButton is sufficient and yet the button is visible for admins only.<\/p>\n<p>If someone&#8217;s interested you can download the source code <a href=\"http:\/\/www.stefan-rinke.de\/download\/jsf-acegi.zip\">here<\/a>.<\/p>\n<p>[\/:en]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>[:de] Spring als Factory f\u00fcr JSF-Components Wie schon im letzten Beitrag &#8220;JSF-Components mit Spring und Velocity-Templates&#8221; soll auch bei diesem Beispiel Spring zum Erzeugen von JSF-Componenten benutzt werden. Noch einmal kurz das Vorgehen: in der faces-config.xml wird mit: eine ApplicationFactory &hellip; <a href=\"https:\/\/cogito-ergo-blog.de\/blog\/2007\/08\/18\/security-fur-jsf-komponenten-mit-spring-aop\/\">Weiterlesen <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9],"tags":[],"_links":{"self":[{"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/posts\/31"}],"collection":[{"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/comments?post=31"}],"version-history":[{"count":5,"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/posts\/31\/revisions"}],"predecessor-version":[{"id":10049,"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/posts\/31\/revisions\/10049"}],"wp:attachment":[{"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/media?parent=31"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/categories?post=31"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/tags?post=31"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}