Additional Blogs by Members
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member

In this blog post we'll look at how one can use Spring Security framework together with the usual way of securing a JEE application on NetWeaver 7.3 and what this can bring us. Here are the useful links :

For the reference, I've tested this setup with Spring Security 3.1.3.RELEASE (which in turn depends on Spring MVC 3.0.7.RELEASE).

Spring Security is a popular and very flexible framework which allows to configure and manage all aspects of securing a web application : authentication, authorization, access control to domain objects. One of the many useful things which this framework provides is a spring-security-taglibs module which allows one to protect the various pieces of the JSP page using security tags tied to the user's role membership (authorization). For example, we can have a JSP like this :

<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>
<p>Hello, this page is accessible to all users with ROLE_EVERYONE</p>
<sec:authorize access="hasRole('ROLE_SFLIGHT_USER')">
    <p>This text and link below should only be visible to users with
    ROLE_SFLIGHT_USER</p>
    <a href="<%=request.getContextPath() %>/secure">secure page</a>
</sec:authorize>

Notice the use of sec:authorize tag which protects access to the part of the page depending on whether or not the current user has a role SFLIGHT_USER. We'll discuss below how we can configure Spring Security to work seamlessly with the security services provided by out JEE container. The idea behind this integration is quite simple: NetWeaver already handles the user authentication for us, there is also a mechanism to map the UME roles of the portal user to the roles referenced in the web.xml of our application. All we have to do is to find a way to make Spring Security framework recognize these roles as the "granted authorities" associated with the authenticated user.

We start with a simple web application set up. Here are the interesting parts of our starting web.xml :

<login-config>
    <auth-method>TICKET</auth-method>
</login-config>
<security-role>
    <role-name>EVERYONE</role-name>
</security-role>
<security-role>
    <role-name>SFLIGHT_USER</role-name>
</security-role>
<security-constraint>
    <web-resource-collection>
        <web-resource-name>Spring Security Integration Test Application</web-resource-name>
        <url-pattern>*</url-pattern>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
        <role-name>EVERYONE</role-name>
    </auth-constraint>
    <user-data-constraint>
        <transport-guarantee>NONE</transport-guarantee>
    </user-data-constraint>
</security-constraint>

We chose a "tiket" authentication method for our web application meaning that the user will be considered authenticated if he or she previously logged in on the portal and that there is JSESSIONID and MYSAPSSO2 cookies are present in his or her browser session (usual SAP SSO via SAP Log on ticket). We declare two security roles "EVERYONE" and "SFLIGHT_USER" for our example. The first one is a general role assigned to every UME user. The other one is an example role which we can create and assign to some test user. We then protect any access to our web application by setting url-pattern of the security constrain to "*". The idea is that we let the JEE container to manage the authentication of the user but the finer granularity access protection within the application we will delegate to Spring Security. For the mapping between the UME roles and the web application security roles we also need this in the web-j2ee-engine.xml file of the web application module :

<security-role-map>
    <role-name>EVERYONE</role-name>
    <server-role-name>EVERYONE</server-role-name>
</security-role-map>
<security-role-map>
    <role-name>SFLIGHT_USER</role-name>
    <server-role-name>SFLIGHT_USER</server-role-name>
</security-role-map>

Now we need to set up and configure the filter chain used by Spring Security. This is done by specifying a Spring's application context file containing all the security configuration in our web.xml file :

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/context/security-config.xml</param-value>
</context-param>
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

The security configuration file, security-config.xml, uses Spring Security namespace for convenience. It uses the security scenario of "pre-authentication" and relies on two classes provided for us by the framework: J2eePreAuthenticatedProcessingFilter and  which integrates with the container authentication process by extracting user principle from the HttpServletRequest and J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource which is responsible to map a configured set of the security roles specified in the web application descriptor file to the set of GrantedAuthorities provided the user membership in these roles has been established. Here is the security-config.xml file :

<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
    <http auto-config="true" use-expressions="true">
        <jee mappable-roles="EVERYONE,SFLIGHT_USER" />
        <intercept-url pattern="/**" access="hasRole('ROLE_EVERYONE')" />
        <intercept-url pattern="/secure/**" access="hasRole('ROLE_EVERYONE')" />
    </http>
    <authentication-manager>
        <authentication-provider ref="preAuthAuthenticationProvider"></authentication-provider>
    </authentication-manager>
    <beans:bean id="preAuthAuthenticationProvider"
        class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
        <beans:property name="preAuthenticatedUserDetailsService">
            <beans:bean
                class="org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesUserDetailsService"></beans:bean>
        </beans:property>
    </beans:bean>
</beans:beans>

Notice the use of "jee" element in the "http" configuration, it is a shortcut for configuring an instance of J2eePreAuthenticatedProcessingFilter filter and registering it with the defaulf filter chain. Also, by default all the JEE security roles specified in the "mappable-roles" attribute will be mapped to the GrantedAuthorities with the names prefixed by "ROLE_".

Once the pre-authentication mechanism is successfully configured we can protect URL access using expressions of the kind "hasRole('ROLE_FROM_UME_HERE')" in the global "http" configuration element and in the security tags in our JSPs. For the reference, this is the Spring MVC configuration file, mvc-config.xml, which I've used for the the web application, it uses "mvc" namespaces for convenience :

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
    <mvc:annotation-driven />
    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>
    <mvc:view-controller path="/" view-name="index"/>
    <mvc:view-controller path="/secure" view-name="secure"/>
</beans>

It could be referenced in the web.xml file in the standard way :

<servlet>
    <servlet-name>springMvcServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/context/mvc-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>springMvcServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

Using Spring Security in the standard JEE web application can be very useful. Other than the use of the security tags in the JSPs, described in this post, one can think of securing method's access in Java beans or using Access Control Lists (ACL) management for example.