-1

I'm implementing spring-session inside my JEE project with Redis. The HttpSession is being saved and updated on my Redis server and I'm able to use it in case of a node failover.

The thing is, my session scoped beans are not getting saved with the session in Redis, and because of this I can't use on a cluster, since the user needs the information stored on the bean to use a lot of functions (steateful).

Am I missing something? I couldn't find a lot of information about this, and since I'm new to Spring, it gets confusing. Is the bean (or can it be) stored with the session in Redis? Here's my implementation:

web.xml:

<context-param>
    <param-name>primefaces.THEME</param-name>
    <param-value>bootstrap</param-value>
</context-param>

<context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Production</param-value>
</context-param>

<servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.faces</url-pattern>
</servlet-mapping>

<session-config>
    <session-timeout>30</session-timeout>
</session-config>
<context-param>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>client</param-value>
</context-param>

<context-param>
    <param-name>
        javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE
    </param-name>
    <param-value>true</param-value>
</context-param>

<context-param>
    <param-name>com.sun.faces.expressionFactory</param-name>
    <param-value>com.sun.el.ExpressionFactoryImpl</param-value>
</context-param>

<welcome-file-list>
    <welcome-file>login.faces</welcome-file>
</welcome-file-list>

<error-page>
    <exception-type>com.exception.InvalidPasswordException</exception-type>
    <location>/ErroServlet</location>
</error-page>
<error-page>
    <exception-type>javax.faces.application.ViewExpiredException</exception-type>
    <location>/login.faces</location>
</error-page>
<error-page>
    <!-- Missing login -->
    <error-code>401</error-code>
    <location>/error.jsp</location>
</error-page>
<error-page>
    <!-- Forbidden directory listing -->
    <error-code>403</error-code>
    <location>/error.jsp</location>
</error-page>
<error-page>  
    <error-code>404</error-code>  
    <location>/error404.jsp</location>  
</error-page> 
<error-page>
    <!-- Uncaught exception -->
    <error-code>500</error-code>
    <location>/error.jsp</location>
</error-page>
<error-page>
    <!-- Unsupported servlet method -->
    <error-code>503</error-code>
    <location>/error.jsp</location>
</error-page>
<error-page>  
    <exception-type>java.lang.Exception</exception-type>  
    <location>/error.jsp</location>  
</error-page>

<listener>
    <listener-class>
        org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>

<listener>
    <listener-class>
        org.springframework.web.context.request.RequestContextListener
    </listener-class>
</listener>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/spring/*.xml
    </param-value>
</context-param>
<listener>

    <listener-class>
        org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>

<filter>
    <filter-name>springSessionRepositoryFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSessionRepositoryFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>

<filter>
    <filter-name>UserCheckFilter</filter-name>
    <filter-class>com.servlet.UserCheckFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>UserCheckFilter</filter-name>
    <url-pattern>/admin/*</url-pattern>
    <url-pattern>/dashboard/*</url-pattern>
</filter-mapping>

<filter>
    <filter-name>UserLogCheckFilter</filter-name>
    <filter-class>com.servlet.UserLogCheckFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>UserLogCheckFilter</filter-name>
    <url-pattern>/login.faces</url-pattern>
</filter-mapping>


<filter>
    <filter-name>AWSXRayServletFilter</filter-name>
    <filter-class>com.amazonaws.xray.javax.servlet.AWSXRayServletFilter</filter-class>
    <init-param>
        <param-name>fixedName</param-name>
        <param-value>app</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>AWSXRayServletFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

session.xml:

<context:annotation-config/>

<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration" />

<bean class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" 
      p:host-name="127.0.0.1" p:port="6379" />

pom.xml:

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>4.3.18.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>4.3.18.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.session</groupId>
        <artifactId>spring-session</artifactId>
        <version>1.3.3.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.session</groupId>
        <artifactId>spring-session-data-redis</artifactId>
        <version>1.3.3.RELEASE</version>
        <type>pom</type>
    </dependency>

Controller: (The abstract controller implements Serializable)

...

@Named
@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class Controller extends AbstractController {

    // EJB to access database using JPA
    @EJB(mappedName = "java:global/app/app-ejb/ControllerService!com.service.ControllerService")
    ControllerService controllerService;

    // A class with my JPA Entity used in the form and some other properties
    private FormFields formFields;

...
trulley
  • 9
  • 2
  • Are you seriously introducing spring in a java-ee project just to be able to store **serialized unreadable** objects in redis? I just read your other Q/A about this and you were advised not to with good and valid reasons... What is your java-ee server I'm sure it has built-in features for this. – Kukeltje Sep 12 '18 at 06:04
  • Check https://www.slideshare.net/mobile/RedisLabs/redisconf17-redis-as-java-session-store – Kukeltje Sep 12 '18 at 06:15
  • Oh and by adding @Component, you are not only introducing spring-session, but the full spring injection/context framework. And having both component and named annotations on a class is wrong... I strongly advise not to go this way – Kukeltje Sep 12 '18 at 07:40
  • Hello Kukeltje, thanks for the feedback! I'm trying to move away from JEE on the web project, so no problem in introducing spring. Of course, as pointed by you, I'm overlooking some important implementations. I'm using Payara. I'm gonna take a look at the slides and give you a feedback. Thanks! – trulley Sep 12 '18 at 13:20

1 Answers1

1

If you want to get session from request, you should add this filter after springSessionRepositoryFilter

<filter>
    <filter-name>requestContextFilter</filter-name>
    <filter-class>org.springframework.web.filter.RequestContextFilter
    </filter-class>
</filter>
<filter-mapping>
    <filter-name>requestContextFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Also I didn't see this configuration in your web.xml which is important to use in cluster

<context-param>
    <param-name>org.apache.myfaces.USE_ENCRYPTION</param-name>
    <param-value>false</param-value>
</context-param>

So when you make USE_ENCRYPTION false your nodes in cluster can retrieve the data in session.

P.S. its important to use https://stackoverflow.com/a/35626681/4431053 when you use client-side state saving instead of making encryption disable. Thanks to @Kukeltje.

Also for Myfaces you can use below configuration for encryption:

 <context-param>
        <param-name>org.apache.myfaces.ALGORITHM</param-name>
        <param-value>AES</param-value>
    </context-param>
    <!-- Defines the secret (Base64 encoded) used to initialize the secret key
         for encryption algorithm. The size of it depends on the algorithm used for encryption -->
    <context-param>
        <param-name>org.apache.myfaces.SECRET</param-name>
        <param-value>MoH3NzQ1Njc4OTAxMjM0NTY3ODkwMTIz</param-value>
    </context-param>
    <!-- Define the initialization code (Bas64 encoded) that are used to initialize the secret key used
         on the Message Authentication Code algorithm. The size of it depends on the algorithm used for mac calculation -->
    <context-param>
        <param-name>org.apache.myfaces.MAC_SECRET</param-name>
        <param-value>SaEiDiEyMzQ=</param-value>
    </context-param>
Mohsen
  • 4,536
  • 2
  • 27
  • 49
  • Seriously, disabling encryption? That is like stating someone should do internet based bankong with plain http (not https) – Kukeltje Dec 09 '19 at 18:24
  • @Kukeltje the encryption is useless when you are using spring security. and Also as you said its totally useless when you are using https – Mohsen Dec 10 '19 at 10:56
  • Can you send me a link where that is stated? Since I have difficulty believing this – Kukeltje Dec 10 '19 at 12:21
  • @Kukeltje when you disable encryption the `javax.faces.ViewState` would not encrypt and it would come in the html page as simple text. It's useless if you are using spring security because in that case the client request would come with session id so it will be ignored and the request would not reach to jsf filter. – Mohsen Dec 10 '19 at 12:27
  • So an authenticated client, in an application that uses client-side state saving and disabled encryption can not manipulate anything when using spring security and https? https://www.alphabot.com/security/blog/2017/java/Misconfigured-JSF-ViewStates-can-lead-to-severe-RCE-vulnerabilities.html – Kukeltje Dec 10 '19 at 13:26
  • @Kukeltje if the application uses client-side state saving the attack you said is possible, but still in server side state saving, encryption is useless. – Mohsen Dec 10 '19 at 15:27
  • Can you please add that to the answer then. Everything like security related configuraton should be as explicit as possible in when to use it and when not. Cheers – Kukeltje Dec 10 '19 at 16:36