Announcement Announcement Module
Collapse
No announcement yet.
Spring-Security + Web Flow + JSF trouble Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring-Security + Web Flow + JSF trouble

    Hi all.
    I have a trouble with creating login process in the application which uses Spring Security, Web Flow and JSF. I have all faces files inherited from the same template. I have also created a login form.

    login.xhtml
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <ui:composition xmlns="http://www.w3.org/1999/xhtml"
    	xmlns:ui="http://java.sun.com/jsf/facelets"
    	xmlns:f="http://java.sun.com/jsf/core"
    	xmlns:h="http://java.sun.com/jsf/html"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:p="http://primefaces.prime.com.tr/ui"
    	xsi:schemaLocation="
            http://java.sun.com/jsf/facelets facelets-ui-2.0.xsd
            http://java.sun.com/jsf/core jsf-core-2.0.xsd
            http://java.sun.com/jsf/html html-basic-2.0.xsd"
    	template="/WEB-INF/layouts/standard.xhtml">
    
    	<ui:define name="content">
    		<h:form prependId="false" action="j_spring_security_check">
    			<div align="center">
    				<h:panelGrid columns="2">
    					<h:outputLabel value="Username *" />
    					<p:inputText id="j_username" />
    					<h:outputLabel value="Password *" />
    					<p:password id="j_password" />
    					<p:commandButton value="Login" action="submit" />
    				</h:panelGrid>
    			</div>
    		</h:form>
    	</ui:define>
    </ui:composition>
    Also I have configured context like this:

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:security="http://www.springframework.org/schema/security"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd
    		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    
    	<security:global-method-security secured-annotations="enabled" />
    
    	<security:http auto-config="true" access-denied-page="/accessDenied.jsp" use-expressions="true">
    		<security:intercept-url pattern="/login.xhtml" filters="none" />
    		<security:intercept-url pattern="/accessDenied.jsp" filters="none" />
    		
    		<security:logout logout-success-url="/" />
    		<security:form-login login-page="/login.xhtml" />		
    	</security:http>
    	
    	
    	<security:authentication-manager>
    		<security:authentication-provider>
    			<security:user-service>
    				<security:user name="rod" password="koala" authorities="ROLE_USER" />
    				<security:user name="dianne" password="emu" authorities="ROLE_USER" />
    				<security:user name="scott" password="wombat" authorities="ROLE_USER" />
    				<security:user name="peter" password="opal" authorities="ROLE_USER" />
    			</security:user-service>
    		</security:authentication-provider>
    	</security:authentication-manager>
    </beans>
    I have added into webflow config uration xml
    Code:
     <bean id="securityFlowExecutionListener" class="org.springframework.webflow.security.SecurityFlowExecutionListener" />
    Added in web.xml

    Code:
    <context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>
            	/WEB-INF/context.xml
            	/WEB-INF/spring/security-config.xml
            </param-value>
    	</context-param>
    
    	<!-- Spring security filter implementation -->
    	
    	<filter>
    		<filter-name>springSecurityFilterChain</filter-name>
    		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    	</filter>
    The main troubles are connected with login.xhtml. If I put it as a view for flow state

    Code:
    	<view-state id="login" view="login.xhtml">
    	</view-state>
    It is shown from menu, but does nothing. When I try to use it as a single login page it is not shown by the browser. Not 404 error, but browser shows blank page. At the same time browser;s view source shows the code from login.xhtml.

    May be somebody can advice me what should be done to make this login form working? All examples in the web tell that there should ne a login bean or login controller. Is it compulsory or there is another way of doing it?

    Thank you in advance.

  • #2
    The main troubles are connected with login.xhtml. If I put it as a view for flow state
    Why do you need to put the login view inside flow? Why don't you let spring security manage the login process?

    Comment


    • #3
      You don't need a controller to map to the login page or create a flow definition for the login page.

      You can register UrlFilenameViewController with FlowHandlerMapping which will resolve URL like
      /login to /WEB-INF/views/login.xhtml using faceletsViewResolver.

      You need to change your security configuration to map the login page to /login instead of login.xhtml.

      Code:
      <security:form-login login-page="/login" ....
      Spring MVC Configuration to map urls to simple pages like login/logout which don't have flow mappings.

      Code:
               <bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
      		<property name="order" value="1" />
      		<property name="flowRegistry" ref="flowRegistry" />
      		<property name="defaultHandler">
      			<!--
      				If no flow match, map path to a view to render; e.g. the "/login"
      				path would map to the view named "login"
      			-->
      			<bean class="org.springframework.web.servlet.mvc.UrlFilenameViewController" />
      		</property>
      		
             </bean>
      
      	<!--
      		Maps logical view names to Facelet templates in /WEB-INF (e.g.
      		'login' to '/WEB-INF/views/login.xhtml'
      	-->
      	<bean id="faceletsViewResolver"
      		class="org.springframework.web.servlet.view.UrlBasedViewResolver">
      		<property name="viewClass" value="org.springframework.faces.mvc.JsfView" />
      		<property name="prefix" value="/WEB-INF/views" />
      		<property name="suffix" value=".xhtml" />
      	</bean>
      
      <!--	Dispatches requests mapped to org.springframework.web.servlet.mvc.Controller implementations  -->
      	<bean
      		class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
      Hope this was helpful.

      Thanks,
      Vijay

      Comment


      • #4
        Thank you for the answer.
        I have solved this problem. In the web.xml
        Code:
        	<context-param>
        		<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
        		<param-value>.xhtml</param-value>
        	</context-param>
        	<servlet-mapping>
        		<servlet-name>Faces Servlet</servlet-name>
        		<url-pattern>*.faces</url-pattern>
        	</servlet-mapping>
        	<servlet>
        		<servlet-name>Faces Servlet</servlet-name>
        		<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        		<load-on-startup>1</load-on-startup>
        	</servlet>
        I have changed the link to login page from /login.xhtml to /login.faces and it works now.

        Comment


        • #5
          Good to know it is working for you, yes for JSF to work with Spring web flow you need to have FacesServlet declared in your web.xml.

          However I would suggest you that it would be cleaner if you could use the spring approach to declare mvc controllers or UrlFilenameViewController as your default handler for FlowHandlerMapping when using with spring web flow.

          Thanks,
          Vijay

          Comment


          • #6
            It's very interesting to hear about spring approach. Could you please give some more information about that?

            Comment


            • #7
              This is the mvc configuration for spring web flow, if you want to map urls to simple pages which don't map to any flows.

              Code:
              <?xml version="1.0" encoding="UTF-8"?>
              <beans xmlns="http://www.springframework.org/schema/beans"
              	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
              	xmlns:faces="http://www.springframework.org/schema/faces"
              	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
              	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
              		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
              		http://www.springframework.org/schema/faces http://www.springframework.org/schema/faces/spring-faces-2.2.xsd
              		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
              		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
              
              	<mvc:resources mapping="/resources/**"
              		location="classpath:/META-INF/web-resources/" />
              	
              	<faces:resources />
              
              	<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
              		<property name="order" value="1" />
              		<property name="flowRegistry" ref="flowRegistry" />
              		<property name="defaultHandler">
              			<!--
              				If no flow match, map path to a view to render; e.g. the "/login"
              				path would map to the view named "login"
              			-->
              			<bean class="org.springframework.web.servlet.mvc.UrlFilenameViewController" />
              		</property>
              
              		<property name="interceptors">
              			<list>
              				<!-- define any interceptors here like openSessionViewInterceptor or localeChangeInterceptor -->				
              			</list>
              		</property>
              	</bean>
              	
              	<!--
              		Maps logical view names to Facelet templates in /WEB-INF/views (e.g.
              		'login' to '/WEB-INF/views/login.xhtml
              	-->
              	<bean id="faceletsViewResolver"
              		class="org.springframework.web.servlet.view.UrlBasedViewResolver">
              		<property name="viewClass" value="org.springframework.faces.mvc.JsfView" />
              		<property name="prefix" value="/WEB-INF/views/" />
              		<property name="suffix" value=".xhtml" />
              	</bean>
              
              	<!--
              		Dispatches requests mapped to
              		org.springframework.web.servlet.mvc.Controller implementations
              	-->
              	<bean
              		class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
              
              	<!--
              		Dispatches requests mapped to flows to FlowHandler implementations
              	-->
              	<bean class="org.springframework.faces.webflow.JsfFlowHandlerAdapter">
              		<property name="flowExecutor" ref="flowExecutor" />
              	</bean>
              
              	<bean id="localeResolver"
              		class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
              		<property name="cookieName" value="language" />
              		<property name="cookieMaxAge" value="3600" />
              		<property name="defaultLocale" value="en" />
              	</bean>
              	
              </beans>
              So any url pattern which doesn't map to any flow e.g. /login will map now to /WEB-INF/views/login.xhtml

              Hence you can configure your spring security config like below:

              Code:
              <security:form-login login-page="/login"...
              Hope this helps..

              Thanks,
              Vijay

              Comment

              Working...
              X