Spring Session Redis with Sticky session on server side for log - redis

Hi i have a Redis configured on my Spring project to use Spring Session, i'm using Jedis 2.9.0 and it works well. The problem I have is with the Sticky session on the Websphere Server, we have 2 main servers and 10 clones of each, with normal httpSession it uses the cookie to handle the request of that cookie to the same server again, good, but with Spring Session it doesn't work the same.
Spring create the cookie with the name "SESSION" and the Load Balancing of Websphere doesn't know where to redirect the request because the session is not on the JVM but is ditributed in Redis Cluster.
i need to (for log order porpuse) handle every request of cookie "abc123" to the server 1 clon 3 for example, and if that instance of the application goes down track that cookie to another instance and stay on that instance until the server goes down again or the user logout...
Searching here and the Spring Session doc, i found something that might be useful but I dont know how it works.
#Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setCookieName("JSESSIONID");
serializer.setCookiePath("/");
serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$");
serializer.setJvmRoute("123");
return serializer;
}
The atribute Jvm Route adds a suffix to the cookie to know whats the JVM that handle that cookie, but i don't know how it works and I haven't been lucky finding examples or explanation about it.
if anyone have the answer or another workaround that i could use it will be great.

Related

Ignite Websession persistance issue with HttpServletResponse.encodeURL

Using Apache Ignite Websession Persistence with Weblogic. The HttpServletResponse.encodeURL method does not work as expected. The issue I'm facing are as follows when cookies are disabled from the browser.
1) Request is sent to node-1 and Ignite creates a new session and when you call HttpServletResponse.encodeURL it appends the 'jsessionId' to the URL and is fine.
2) When you hit the node-2 with the encoded URL from node-1, Ignite is able to pull the session from the Ignite Cache and doesn't create a new session, but when you call encodeURL it doesn't append the 'jsessionid'. This is because the response object has a reference to the Weblogic's HTTPRequest/session objects and not the Ignite wrapper HTTPServleteRequestObjects and it doesn't append the sessionId to the URL.
The only way I can workaround this issue is to override the implementation of encodeURL and encodeRedirectURL methods which I don't prefer as it could be error prone.
Has anybody else faced this issue and found a good solution ?

Spring boot 1.3.1 with Tyrus websocket causes Authentication Exception

We recently migrated to Spring boot 1.3.1 from the traditional spring project.
Our existing clients use Tyrus 1.12 as a websocket client.
After the upgrade, we found that the clients no longer connect and throws AuthenticationException. Strangely, they are able to connect for the first time since server restart and soon after throws AuthenticationException.
Digging a bit more, I found that Tyrus receives a 401 initially and passes on credentials subsequently. The server logs indicate the same behaviour, by first assigning ROLE_ANONYMOUS and then the correct role, ROLE_GUEST there after.
It seems like after the negotiation, the server closes connection and disconnects.
I observed the same behaviour when using spring stomp websocket client with Tyrus.
ClientManager container = ClientManager.createClient();
container.getProperties().put("org.glassfish.tyrus.client.sharedContainer", true);
container.getProperties().put(ClientProperties.CREDENTIALS, new Credentials("guest", "guest"));
StandardWebSocketClient webSocketClient = new StandardWebSocketClient(container);
final CountDownLatch messageLatch = new CountDownLatch(10);
WebSocketStompClient stompClient = new WebSocketStompClient(webSocketClient);
This same server setup works fine when the credentials are sent in the header.
stompClient.connect(url, getHandshakeHeaders("guest", "guest"), handler);
And this will NOT work since the credentials are not in the header
ListenableFuture<StompSession>session = stompClient.connect(url, handler, "localhost", "8080");
I am not understanding why it is working one way and not the other.
After upgrading to spring-boot, our software is no longer backwards compatible and will have to ask all our external clients to inject the authorization in the header before receiving a 401.
Can someone please help?
My earlier post with stacktrace

Same Session is being used for Multiple requests

We have developed an application where after a successful request, session has to be destroyed. This is working fine, when we have a single tomcat.
But, this is not happening when we use multiple tomcats under Apache simple load balancer (We are using Load Balancer, for balancing the requests between two tomcats, which are hosting the same application).
The SessionID that is created and have processed successfully, can be used for one more transaction, after which it is getting killed.
Moreover, the SessionID value is being appended with either 'n1' or 'n2' (SessionID-n1). I am not sure of why is this happening.
Please help me to resolve this issue.
We have a configuration setup as below:
Load Balancer
/ \
Cluster1 Cluster2
| |
Tomcat1 Tomcat2
Thanks,
Sandeep
If you have configured each Tomcat node to have a "jvmRoute", then the string you specify there will be appended to the session identifier. This can help your load-balancer determine which back-end server should be used to serve a particular request. It sounds like this is exactly what you have done. Check your CATALINA_BASE/conf/server.xml file for the word "jvmRoute" to confirm.
If you only use a session for a single transaction, why are you bothering to create the session in the first place? Is a request == transaction?
If you are sure you are terminating the session when the transaction is complete, you should be okay even if the client wants to try to make a new request with the same session id. It will no longer be valid and therefore useless to the client.
It's not clear from your question whether there is an actual problem with the session because you claim it is "getting killed" which sounds like what you want it to do. If you provide more detail on the session expiration thing, I'll modify my answer accordingly.

OOM Error on JBoss 4.11

We are maintaining an application which uses Jboss as its AS. Recently customer complained about OOM error and he was unable to login. We restarted Jboss and added configurations to collect heapdump.
Customer's application usage pattern: Customer opens a page containing 10 charts which are rendered in an inframe. Flex is used for UI. This page refreshes itself every 5 minutes.
Request Flow: The application is built in such a way that all the requests go through Apache (Http) proxy server. Every 5 minutes the dashboard request has to pass through Apache proxy server.
After 5 days OOM error occurred and on analyzing the heapdump we noticed that the error was due to "org.apache.catalina.session.StandardSession", loaded by "org.jboss.mx.loading.UnifiedClassLoader3 # 0x7b440dd70" occupy 1,776,569,336 (87.71%) bytes.
Full description is:
847,599 instances of "org.apache.catalina.session.StandardSession", loaded by "org.jboss.mx.loading.UnifiedClassLoader3 # 0x7b440dd70" occupy 1,776,569,336 (87.71%) bytes. These instances are referenced from one instance of "org.apache.catalina.Session[]", loaded by "org.jboss.mx.loading.UnifiedClassLoader3 # 0x7b440dd70"
Keywords
org.jboss.mx.loading.UnifiedClassLoader3 # 0x7b440dd70
org.apache.catalina.session.StandardSession
org.apache.catalina.Session[]
Common Path To the Accumulation Point says:
java.lang.Thread # 0x7b4a5f358 ContainerBackgroundProcessor[StandardEngine[jboss.web]]
org.apache.catalina.session.StandardSession # 0x797b49b70
I am new to Jboss and proxy servers. How to debug this issue? Could you please help me.
Thanks
M
org.apache.catalina.session.StandardSession is a class representing user http session. I would say, that your every request creates new http session on JBoss which is never expired. Either pass session cookie back to JBoss with every refresh to reuse sessions and not to create new ones. Or configure sensible http session expiration policy in you JBoss.
Good luck,
Plumbr team

How to manually set/propagate security context information e.g. Principal for JBoss 7 (over JBoss remoting 2)

I'm using jboss remoting 2.5.4.SP3 to provide remote access to EJBs in a JBoss 7.1 server from both a web app and other JBoss instances. I'm doing it manually because of issues with remote EJB access in JBoss 7.1, specifically (but not only) the inability to access the same (interface) bean on multiple servers simultaneously. I'm using remoting2 because remoting3 has no documentation.
I have remoting working using TransporterHandle/TransporterClient using the socket transport, but in methods called via this remote connection, the server wants to lookup the principal from the ejbContext. I can't find a way to manually set the principal, or other contextual security/identity information. At the limit I'd be happy just to set the principal when the ejb method is invoked - all incoming calls are to local EJB3 beans - or even to set it specifically for the EJBContext.
I've found a lot of information regarding Spring (which I'm not using), but nothing seems to match my particular context.
And now, the correct way to do this:
On the client side I get the security context and package up the security domain and subject info for transport to the server along with the invocation. The SecurityDomain is a String and SubjectInfo is serializable:
Map m = new HashMap();
SecurityContext securityContext = SecurityContextAssociation.getSecurityContext();
if (securityContext != null) {
m.put("SUBJECT-INFO", securityContext.getSubjectInfo());
m.put("SECURITY-DOMAIN", securityContext.getSecurityDomain());
}
response = remotingClient.invoke(request, m);
The map m gets sent with the invocation over jboss remoting. On the server side, I extract the security information and set the context for the invocation like this:
SecurityContext oldContext = SecurityContextAssociation.getSecurityContext();
SubjectInfo si = (SubjectInfo) invocation.getRequestPayload().get("SUBJECT-INFO");
String domain = (String) invocation.getRequestPayload().get("SECURITY-DOMAIN");
if (si != null) {
SecurityContext sc = new JBossSecurityContext(domain);
sc.setSubjectInfo(si);
SecurityContextAssociation.setSecurityContext(sc);
}
try {
return super.invoke(invocation);
} finally {
SecurityContextAssociation.setSecurityContext(oldContext);
}
Works like a charm!
Have a look at the jboss-ejb-client.properties. There is also a quickstart example using a remote client to lookup an EJB.
I've solved my underlying problem, although not in the general way I was hoping for.
I put a servlet filter on all incoming requests, recording request.getUserPrincipal in a thread local. I can then access this in non-EE code and find the principal making the request. Then when I make call to my app server I use JBoss Remoting's ability to attach metadata to each invocation to pass the Principal over the wire. I had to copy the TransporterClient to do this because it's private constructors et al don't allow for overriding the functionality required to attach per-request metadata (as opposed to per-connection). On the server side I take the incoming Principal and set it into a thread local. Then, in subsequent code that accesses EJBContext.getCallerPrincipal I also lookup the incoming Principal from the thread local, and if that isn't null (hence we are in a remote EJB call), I use that if the caller principal is anonymous. If it's not anonymous then it must have been set in some way after the incoming call, so I ignore the incoming Principal in that case.
All in all, a much more specialised solution than I was hoping for, and it doesn't shed any light on how I can do generic context propagation in JBoss 7.1 over the wire.