Liferay Session mod_jk issue - java

The session is not working with mod_jk load balancer (from httpd web server). However, the same code is working fine in the application server.
Following is worker.properties:
worker.list=loadbalancer,status,web
worker.node0.port=8009
worker.node0.host=10.50.26.19
worker.node0.type=ajp13
worker.node0.lbfactor=1
worker.node0.socket_keepalive=false
worker.node0.connect_timeout=10000
worker.node0.prepost_timeout=10000
worker.node0.socket_timeout=60
worker.node0.connection_pool_timeout=600
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=node0
worker.loadbalancer.sticky_session=1
Java Code in Portlet 1:
PortletSession portletSession = actionRequest.getPortletSession();
portletSession.setAttribute("username",reg.getFname(), PortletSession.APPLICATION_SCOPE);
JSP Code in Portlet 2:
PortletSession portletSessionobject = renderRequest.getPortletSession();
userName=(String)portletSessionobject.getAttribute("username",PortletSession.APPLICATION_SCOPE);
In both the portlet the following property have been applied in the liferay-portlet.xml
<private-session-attributes>false</private-session-attributes>
But unable to get username in the Portlet 2 JSP page in web server it is returning null. But in the application server the value is coming as expected. Please suggest.

After doing much research found the solution. Hence posting it to help others. There are two things that cause the issue.
i) The sessions were overwritten by the httpd server. Following header tag was added in the httpd.conf which actually caused the issue. Removed it and JSESSION started to appear.
Header set Set-Cookie HttpOnly;Secure
ii) Session Affinity was not working properly due to jvmRoute was not defined. As a result, the session gets terminated intermittently. So added the instance-id for subsystem web in the standalone.xml of each instance,
For node0,
<subsystem xmlns="urn:jboss:domain:web:1.1" default-virtual-server="default-host" instance-id="node0" native="false">
For node1,
<subsystem xmlns="urn:jboss:domain:web:1.1" default-virtual-server="default-host" instance-id="node1" native="false">

Related

Cannot stop Spring redirecting https to http

I'm developing project on a Spring Security and everything was going fine until I loaded my project to a production server. I have only http on my local machine but there is https on a production server.
And I faced an error (in case of login error):
Mixed Content: The page at 'https://my.production.com/login' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://my.production.com/api/login?error=bad-credentials'. This request has been blocked; the content must be served over HTTPS.
and (in case of success login):
Mixed Content: The page at 'https://my.production.com/login' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://my.production.com/authorities'. This request has been blocked; the content must be served over HTTPS.
I asked my vendor about this issue but they say that "There is no https between you app and nginx, so this is your app problem"...
I tried this, but this solution looks very weird and doesn't solve problem (It requires adding a lot of configuration classes and I guess it shouldn't be so hard). Actually I'm very confused how can this happen, why isn't it the default behavior to redirect to the schema that the request was made...
Also I tried adding this to my Spring Security config:
.and().requiresChannel().anyRequest().requiresSecure()
but this only causes ERR_TOO_MANY_REDIRECTS on my local machine and on a production server...
This didn't help too:
http.portMapper()
.http(8080).mapsTo(8443);
I'm not using Spring boot, but also tried this, no help.
Success authentication configuration looks like this:
SavedRequestAwareAuthenticationSuccessHandler successHandler = new
SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setDefaultTargetUrl(env.getProperty("app.authenticationSuccessUrl"));
When Apache Tomcat is running behind a HTTPS (reverse) proxy, there may be some configuration required for links and redirects to work properly.
Open conf/server.xml, find the Connector element, add the following attributes if not already present:
proxyName - set to your domain name.
proxyPort - set it to 443 if you are using the standard https port.
scheme - set to "https" if site is accessed with https.
secure - set to "true" for https.
<Connector proxyName="my.production.com" proxyPort="443" scheme="https" secure="true" ...>
Reference: Apache Tomcat 7: The HTTP Connector

Creating Cookie/Session in Tomcat [duplicate]

I have been looking at solutions for sharing session data between mutliple war files. I came across the following solution http://www.fwd.at/tomcat/sharing-session-data-howto.html
The basic idea of it is that if you have more than one war file, you can set a cookie using the sessionid of the first context that is used.
The cookie can be set using a path that will apply to all contexts/applications.
For example, if I have the following configuration for 3 applications
/myapp/app1
/myapp/app2
/myapp/app3
I can set a cookie as follows
/myapp sessionid.
The sessionid cookie will then be sent to any request with /myapp in the address. This allows the session id to then be used by any of the contexts.
The only problem with this approach is that it was written in 2003 and tested on Tomcat 4.
What are your opinions of this approach? Is there a better way of doing it?
Thanks
That article is indeed heavily outdated.
On Tomcat 5.5 and 6.0 you can just set emptySessionPath attribute to true in the <Connector> element in /conf/server.xml.
<Connector ... emptySessionPath="true">
On Tomcat 7.0 this has changed because this is now configureable from the Servlet 3.0 API on. It's then on Tomcat's side configureable by setting sessionCookiePath to / in <Context> element in any responsible context.xml file.
<Context ... sessionCookiePath="/">
As said, there's a new Servlet 3.0 API which allows you to configure the session cookie through the standard API. You can do it either declaratively by adding the following to the web.xml:
<session-config>
<cookie-config>
<path>/</path>
</cookie-config>
</session-config>
or programmatically by SessionCookieConfig which is available by ServletContext#getSessionCookieConfig().
getServletContext().getSessionCookieConfig().setPath("/");
You could do this in ServletContextListener#contextInitialized() or HttpServlet#init().
See also:
Tomcat 5.5 HTTP connector documentation
Tomcat 6.0 HTTP connector documentation - mentions potential security hole
Tomcat 7.0 context documentation
To my knowledge there is no direct way to do this, you can however use a domain level cookie if these contexts share the same domain.
You can either put the data in the cookie (I don't recommend that).
Or put a secured session Id that you can use to access some form of storage (DB or distributed cache etc) to retrieve the data you need.
If the amount of data is not astronomical and the data itself isn't changing too rapidly, you might want to consider using JNDI. This solution was designed exactly for what you are looking for.
You can have a look at official documentation or this post to tomcat-user mailing list for references & examples.
For Tomcat 8 I use the following configuration to share a session across 2 webapps:
conf/context.xml
<Context sessionCookiePath="/">
<Valve className="org.apache.catalina.valves.PersistentValve"/>
<Manager className="org.apache.catalina.session.PersistentManager">
<Store className="org.apache.catalina.session.FileStore" directory="${catalina.base}/temp/sessions"/>
</Manager>
...
</Context>
I deploy the same simple webapp twice log.war and log2.war:
/log
/log2
I can now log-in to /log and have the user displayed in /log2, this does not work with the tomcat default configuration.
The session value is set and read:
HttpSession session=request.getSession();
session.setAttribute("name",name);
HttpSession session=request.getSession(false);
String name=(String)session.getAttribute("name");
I used this project as example: https://www.javatpoint.com/servlet-http-session-login-and-logout-example
Most examples/solutions use a in-memory database which requires more setup work:
redis
hazelcast

Apache Tomcat 7 Changing JSESSIONID on Every Request

This issue is driving me insane, so maybe someone could help me understand what the issue is. I have a tomcat web application being fronted by HAProxy. HAProxy is also doing SSL offloading, and is configured to use sticky sessions. I am using Tomcat's session replication feature which seems to be working just fine. The sessions appear on both appservers.
For some reason, Tomcat is generating a new JSESSIONID for every single web request, and then copying the contents of the old session into the new session. That is to say, my session contents are still there within the new session, but a new ID is generated and sent back to the client. But it only does this for my web application. It does not do this for the /manager application.
I have tried every trick in the book, such as setting this in my context.xml:
<Valve className="org.apache.catalina.authenticator.BasicAuthenticator" changeSessionIdOnAuthentication="false" />
And setting these attributes on my Context element:
<Context path="/myapp" reloadable="false" override="true" useNaming="false" allowLinking="true" useHttpOnly="false" sessionCookiePath="/" sessionCookiePathUsesTrailingSlash="false">
And still, the result is the same. Tomcat generates a new session id with every request and copies the contents of the old session into the new id.
I would suspect it had something to do with HAProxy, except that the /manager application is also behind HAProxy and it does not exhibit this behavior.
Why is Tomcat doing this, and what can I do to prevent it?
Turns out that it was cause by Spring Security. We are using Spring Security 3.1x, and by default it stores the authenticated credentials in the user's session. And to counter session fixation attacks, it automatically copies the contents of the user's session to a new session id and invalidates the old session.
The fix was to add the following to the http element in the security configuration, since we don't need to use the session in our application:
create-session="stateless"
Hopefully this helps someone else down the line.
I got the same problem with new id session when I refresh page
On tomcat7 server, I only add into the context.xml this code :
<Valve className="org.apache.catalina.authenticator.BasicAuthenticator" changeSessionIdOnAuthentication="false" />
<Context path="/myapp" reloadable="false" override="true" useNaming="false" allowLinking="true" useHttpOnly="false" sessionCookiePath="/" sessionCookiePathUsesTrailingSlash="false">
This work fine for me.
Not sure exactly what your problem is, but there are two things I would check. First, did you specify the jvmRoute in tomcat?
Tomcat server.xml
<Engine name="Catalina" defaultHost="localhost" jvmRoute="machine1">
Haproxy.cfg (references jvmRoute)
server machine1 SERVER_IP cookie machine1 check
Tomcat appends the name of the server to the cookie, so not setting that can cause issues.
The other thing to check is to make sure that you added this line to your web.xml in the web-app section
<distributable />

Sharing session data between contexts in Tomcat

I have been looking at solutions for sharing session data between mutliple war files. I came across the following solution http://www.fwd.at/tomcat/sharing-session-data-howto.html
The basic idea of it is that if you have more than one war file, you can set a cookie using the sessionid of the first context that is used.
The cookie can be set using a path that will apply to all contexts/applications.
For example, if I have the following configuration for 3 applications
/myapp/app1
/myapp/app2
/myapp/app3
I can set a cookie as follows
/myapp sessionid.
The sessionid cookie will then be sent to any request with /myapp in the address. This allows the session id to then be used by any of the contexts.
The only problem with this approach is that it was written in 2003 and tested on Tomcat 4.
What are your opinions of this approach? Is there a better way of doing it?
Thanks
That article is indeed heavily outdated.
On Tomcat 5.5 and 6.0 you can just set emptySessionPath attribute to true in the <Connector> element in /conf/server.xml.
<Connector ... emptySessionPath="true">
On Tomcat 7.0 this has changed because this is now configureable from the Servlet 3.0 API on. It's then on Tomcat's side configureable by setting sessionCookiePath to / in <Context> element in any responsible context.xml file.
<Context ... sessionCookiePath="/">
As said, there's a new Servlet 3.0 API which allows you to configure the session cookie through the standard API. You can do it either declaratively by adding the following to the web.xml:
<session-config>
<cookie-config>
<path>/</path>
</cookie-config>
</session-config>
or programmatically by SessionCookieConfig which is available by ServletContext#getSessionCookieConfig().
getServletContext().getSessionCookieConfig().setPath("/");
You could do this in ServletContextListener#contextInitialized() or HttpServlet#init().
See also:
Tomcat 5.5 HTTP connector documentation
Tomcat 6.0 HTTP connector documentation - mentions potential security hole
Tomcat 7.0 context documentation
To my knowledge there is no direct way to do this, you can however use a domain level cookie if these contexts share the same domain.
You can either put the data in the cookie (I don't recommend that).
Or put a secured session Id that you can use to access some form of storage (DB or distributed cache etc) to retrieve the data you need.
If the amount of data is not astronomical and the data itself isn't changing too rapidly, you might want to consider using JNDI. This solution was designed exactly for what you are looking for.
You can have a look at official documentation or this post to tomcat-user mailing list for references & examples.
For Tomcat 8 I use the following configuration to share a session across 2 webapps:
conf/context.xml
<Context sessionCookiePath="/">
<Valve className="org.apache.catalina.valves.PersistentValve"/>
<Manager className="org.apache.catalina.session.PersistentManager">
<Store className="org.apache.catalina.session.FileStore" directory="${catalina.base}/temp/sessions"/>
</Manager>
...
</Context>
I deploy the same simple webapp twice log.war and log2.war:
/log
/log2
I can now log-in to /log and have the user displayed in /log2, this does not work with the tomcat default configuration.
The session value is set and read:
HttpSession session=request.getSession();
session.setAttribute("name",name);
HttpSession session=request.getSession(false);
String name=(String)session.getAttribute("name");
I used this project as example: https://www.javatpoint.com/servlet-http-session-login-and-logout-example
Most examples/solutions use a in-memory database which requires more setup work:
redis
hazelcast

Spring security doesn't work on Glassfish v3

I have a java web application that use spring security for log in users, restriction access etc. , and it is working without problems on Glassfish 2.1, Tomcat, jetty, but on glassfish v3 doesn't work, when I try to login, and press button login, I'm getting login box from glassfish server(the box "The server xxxx requires user name and password").
Has somebody got such issue? Please let me know how I can solve this.
Thanks,
Iurie
Try to comment the following fragment:
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
in ".../glassfish/domains/domain1/config/default-web.xml" file
I don't know what is causing this (and potentially it could be one of a number of things), but I suggest that you turn the logging level up to the max and see if that gives you some clues as to what is going on. (When the logging level is DEBUG or higher, SpringSecurity generates lots of logging.)
... the request is not sent to spring security, the glassfish stopped it with his basic authentication, the question is why.
I don't know what the cause of this is, but it sounds like some aspect of Glassfish authentication / authorization needs to be turned off if you want to use SpringSecurity. (Maybe you did this in your Glassfish 2.1 installation ...)
The way that SpringSecurity works, you will definitely see logging messages if a request goes to a servlet that has the SS filter chain in place. It is possible that there is a SS misconfiguration that means that you've not got the SS filter chain in place, but I suspect that the real problem is that Glassfish is doing its bit before the requests get sent to the filter chain.
Did you create a JDBC Connection pool and Resource in Glassfish server?
For ex:
User: root
Password: java
databaseName: theDatabase
serverName: localhost
portNumber: 3306
driverClass: com.mysql.jdbc.Driver
URL: jdbc:mysql://localhost:3306/dbname
The issue seems to be confusion over the /j_spring_security_check url, if you change it everything works again.
<security:form-login login-processing-url="/whatever_security_check" />
See this.

Categories

Resources