From 8da90c1f897736d2d2237efedd2b6a3ac362af2d Mon Sep 17 00:00:00 2001
From: Christian Maierhofer <cmaierhofer@iaik.tugraz.at>
Date: Wed, 27 Apr 2016 16:11:49 +0200
Subject: Modified SingleLogOutAction to work with REDIS

---
 .../moa/id/protocols/pvp2x/SingleLogOutAction.java | 274 +++++++++++----------
 .../moa/id/storage/DBTransactionStorage.java       |  13 +-
 .../moa/id/storage/ITransactionStorage.java        |  17 ++
 .../moa/id/storage/RedisTransactionStorage.java    |  22 ++
 4 files changed, 192 insertions(+), 134 deletions(-)

(limited to 'id/server/idserverlib')

diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java
index d7adab4e6..57540138e 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java
@@ -83,8 +83,8 @@ public class SingleLogOutAction implements IAction {
 	@Autowired private ITransactionStorage transactionStorage;
 	@Autowired private SingleLogOutBuilder sloBuilder;
 	@Autowired private MOAReversionLogger revisionsLogger;
-	
-	
+
+
 	/* (non-Javadoc)
 	 * @see at.gv.egovernment.moa.id.moduls.IAction#processRequest(at.gv.egovernment.moa.id.moduls.IRequest, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, at.gv.egovernment.moa.id.data.IAuthData)
 	 */
@@ -94,139 +94,145 @@ public class SingleLogOutAction implements IAction {
 			IAuthData authData) throws MOAIDException {
 
 		PVPTargetConfiguration pvpReq = (PVPTargetConfiguration) req;  
-				
+
 		if (pvpReq.getRequest() instanceof MOARequest &&
 				((MOARequest)pvpReq.getRequest()).getSamlRequest() instanceof LogoutRequest) {
 			Logger.debug("Process Single LogOut request");
 			MOARequest samlReq = (MOARequest) pvpReq.getRequest();
 			LogoutRequest logOutReq = (LogoutRequest) samlReq.getSamlRequest();
-				
+
 			AuthenticationSession session = 
 					authenticationSessionStorage.searchMOASessionWithNameIDandOAID(
 							logOutReq.getIssuer().getValue(), 
 							logOutReq.getNameID().getValue());
-				
-				if (session == null) {
-					Logger.warn("Can not find active SSO session with nameID " 
-							+ logOutReq.getNameID().getValue() + " and OA " 
-							+ logOutReq.getIssuer().getValue());
-					Logger.info("Search active SSO session with SSO session cookie");
-					String ssoID = ssomanager.getSSOSessionID(httpReq);
-					if (MiscUtil.isEmpty(ssoID)) {
+
+			if (session == null) {
+				Logger.warn("Can not find active SSO session with nameID " 
+						+ logOutReq.getNameID().getValue() + " and OA " 
+						+ logOutReq.getIssuer().getValue());
+				Logger.info("Search active SSO session with SSO session cookie");
+				String ssoID = ssomanager.getSSOSessionID(httpReq);
+				if (MiscUtil.isEmpty(ssoID)) {
+					Logger.info("Can not find active Session. Single LogOut not possible!");
+					SingleLogoutService sloService = sloBuilder.getResponseSLODescriptor(pvpReq);
+					//LogoutResponse message = sloBuilder.buildSLOErrorResponse(sloService, pvpReq, StatusCode.RESPONDER_URI);
+					LogoutResponse message = sloBuilder.buildSLOResponseMessage(sloService, pvpReq, null);
+					Logger.info("Sending SLO success message to requester ...");
+					sloBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState());						
+					return null;
+
+				} else {
+					String moasession = ssomanager.getMOASession(ssoID);						
+					try {
+						session = authenticationSessionStorage.getSession(moasession);
+
+					} catch (MOADatabaseException e) {
 						Logger.info("Can not find active Session. Single LogOut not possible!");
 						SingleLogoutService sloService = sloBuilder.getResponseSLODescriptor(pvpReq);
 						//LogoutResponse message = sloBuilder.buildSLOErrorResponse(sloService, pvpReq, StatusCode.RESPONDER_URI);
 						LogoutResponse message = sloBuilder.buildSLOResponseMessage(sloService, pvpReq, null);
 						Logger.info("Sending SLO success message to requester ...");
-						sloBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState());						
+						sloBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState());
 						return null;
-						
-					} else {
-						String moasession = ssomanager.getMOASession(ssoID);						
-						try {
-							session = authenticationSessionStorage.getSession(moasession);
-														
-						} catch (MOADatabaseException e) {
-							Logger.info("Can not find active Session. Single LogOut not possible!");
-							SingleLogoutService sloService = sloBuilder.getResponseSLODescriptor(pvpReq);
-							//LogoutResponse message = sloBuilder.buildSLOErrorResponse(sloService, pvpReq, StatusCode.RESPONDER_URI);
-							LogoutResponse message = sloBuilder.buildSLOResponseMessage(sloService, pvpReq, null);
-							Logger.info("Sending SLO success message to requester ...");
-							sloBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState());
-							return null;
-							
-						}						
-					}					
+
+					}						
+				}					
+			}
+
+			authManager.performSingleLogOut(httpReq, httpResp, session, pvpReq);
+
+		} else if (pvpReq.getRequest() instanceof MOAResponse &&
+				((MOAResponse)pvpReq.getRequest()).getResponse() instanceof LogoutResponse) {
+			Logger.debug("Process Single LogOut response");
+			LogoutResponse logOutResp = (LogoutResponse) ((MOAResponse)pvpReq.getRequest()).getResponse();
+
+			//Transaction tx = null;
+
+			try {					
+				String relayState = pvpReq.getRequest().getRelayState();
+				if (MiscUtil.isEmpty(relayState)) {
+					Logger.warn("SLO Response from " + logOutResp.getIssuer().getValue() 
+							+ " has no SAML2 RelayState.");					
+					throw new SLOException("pvp2.19", null);
+
 				}
-				
-				authManager.performSingleLogOut(httpReq, httpResp, session, pvpReq);
-							
-			} else if (pvpReq.getRequest() instanceof MOAResponse &&
-					((MOAResponse)pvpReq.getRequest()).getResponse() instanceof LogoutResponse) {
-				Logger.debug("Process Single LogOut response");
-				LogoutResponse logOutResp = (LogoutResponse) ((MOAResponse)pvpReq.getRequest()).getResponse();
-
-				Transaction tx = null;
-				
-				try {					
-					String relayState = pvpReq.getRequest().getRelayState();
-					if (MiscUtil.isEmpty(relayState)) {
-						Logger.warn("SLO Response from " + logOutResp.getIssuer().getValue() 
-								+ " has no SAML2 RelayState.");					
-						throw new SLOException("pvp2.19", null);
-						
-					}
-					
-					Session session = MOASessionDBUtils.getCurrentSession();					
-					boolean storageSuccess = false;
-					int counter = 0;
-					
-					//TODO: add counter to prevent deadlock
-					
+
+				//Session session = MOASessionDBUtils.getCurrentSession();					
+				boolean storageSuccess = false;
+				int counter = 0;
+
+				//TODO: add counter to prevent deadlock
+				synchronized(this){
 					while (!storageSuccess) {
-						tx = session.beginTransaction();
-						
-						List result;
-						Query query = session.getNamedQuery("getAssertionWithArtifact");
-						query.setParameter("artifact", relayState);
-						result = query.list();					  
-						Logger.trace("Found entries: " + result.size());
-						  
-						//Assertion requires an unique artifact
-						if (result.size() != 1) {
+						//						tx = session.beginTransaction();
+						//						
+						//						List result;
+						//						Query query = session.getNamedQuery("getAssertionWithArtifact");
+						//						query.setParameter("artifact", relayState);
+						//						result = query.list();					  
+						//						
+						//						
+						//						Logger.trace("Found entries: " + result.size());
+						//						  
+						//						//Assertion requires an unique artifact
+						//						if (result.size() != 1) {
+						//							Logger.trace("No entries found.");
+						//						   	throw new MOADatabaseException("No sessioninformation found with this ID");
+						//						}
+						//						  
+						//						AssertionStore element = (AssertionStore) result.get(0);					
+						//						Object data = SerializationUtils.deserialize(element.getAssertion());
+						Logger.debug("Current Thread getAssertionStore: "+Thread.currentThread().getId());
+						Object o = transactionStorage.getAssertionStore(relayState);
+						if(o==null){
 							Logger.trace("No entries found.");
-						   	throw new MOADatabaseException("No sessioninformation found with this ID");
+							throw new MOADatabaseException("No sessioninformation found with this ID");
 						}
-						  
-						AssertionStore element = (AssertionStore) result.get(0);					
-						Object data = SerializationUtils.deserialize(element.getAssertion());
-						
+						AssertionStore element = (AssertionStore) o;
+						Object data = SerializationUtils.deserialize(element.getAssertion());	
+
 						if (data instanceof SLOInformationContainer) {
 							ISLOInformationContainer sloContainer = (ISLOInformationContainer) data;
-							
+
 							//check status
 							sloBuilder.checkStatusCode(sloContainer, logOutResp);
-														
+
 							if (sloContainer.hasFrontChannelOA()) {							
 								try {
 									//some response are open
 									byte[] serializedSLOContainer = SerializationUtils.serialize((Serializable) sloContainer);
 									element.setAssertion(serializedSLOContainer);
 									element.setType(sloContainer.getClass().getName());
-							
-									session.saveOrUpdate(element);							
-									tx.commit();
-									
+
+									//									session.saveOrUpdate(element);							
+									//									tx.commit();
+									Logger.debug("Current Thread putAssertionStore: "+Thread.currentThread().getId());
+									transactionStorage.putAssertionStore(element);
+
 									//sloContainer could be stored to database
 									storageSuccess = true;
-									
-								} catch(HibernateException e) {
-									tx.rollback();
+
+								} catch(MOADatabaseException e) {
+									//tx.rollback();
 
 									counter++;									
 									Logger.debug("SLOContainter could not stored to database. Wait some time and restart storage process ... ");
 									java.util.Random rand = new java.util.Random();
-									
+
 									try {
 										Thread.sleep(rand.nextInt(20)*10);
-										
+
 									} catch (InterruptedException e1) {
 										Logger.warn("Thread could not stopped. ReStart storage process immediately", e1);
 									}																	
 								}
-								
+
 							} else {
-								//last response received.
-								try {
-									session.delete(element);
-									tx.commit();
-									
-								} catch(HibernateException e) {
-									tx.rollback();								
-									Logger.error("SLOContainter could not deleted from database. ");
-									
-								}
-									
+								Logger.debug("Current Thread removeElement by Artifact: "+Thread.currentThread().getId());
+								transactionStorage.remove(element.getArtifact());
+								//									session.delete(element);
+								//									tx.commit();
+
 								storageSuccess = true;
 								String redirectURL = null;
 								if (sloContainer.getSloRequest() != null) {
@@ -234,70 +240,72 @@ public class SingleLogOutAction implements IAction {
 									SingleLogoutService sloService = sloBuilder.getResponseSLODescriptor(sloContainer.getSloRequest());
 									LogoutResponse message = sloBuilder.buildSLOResponseMessage(sloService, sloContainer.getSloRequest(), sloContainer.getSloFailedOAs());
 									redirectURL = sloBuilder.getFrontChannelSLOMessageURL(sloService, message, httpReq, httpResp, sloContainer.getSloRequest().getRequest().getRelayState());
-																	
+
 								} else {
 									//print SLO information directly
 									redirectURL = req.getAuthURL() + "/idpSingleLogout";
-									
+
 									String artifact = Random.nextRandom();
-									
-							        String statusCode = null;
+
+									String statusCode = null;
 									if (sloContainer.getSloFailedOAs() == null || 
-							        		sloContainer.getSloFailedOAs().size() == 0) {							       							   							        	
-							        	statusCode  = MOAIDAuthConstants.SLOSTATUS_SUCCESS;
-							        	revisionsLogger.logEvent(sloContainer.getSessionID(), sloContainer.getTransactionID(),
-							        			MOAIDEventConstants.AUTHPROCESS_SLO_ALL_VALID);
-							        	
+											sloContainer.getSloFailedOAs().size() == 0) {							       							   							        	
+										statusCode  = MOAIDAuthConstants.SLOSTATUS_SUCCESS;
+										revisionsLogger.logEvent(sloContainer.getSessionID(), sloContainer.getTransactionID(),
+												MOAIDEventConstants.AUTHPROCESS_SLO_ALL_VALID);
+
 									} else {
 										revisionsLogger.logEvent(sloContainer.getSessionID(), sloContainer.getTransactionID(), 
 												MOAIDEventConstants.AUTHPROCESS_SLO_NOT_ALL_VALID);
-							        	statusCode  = MOAIDAuthConstants.SLOSTATUS_ERROR;
-							        	
+										statusCode  = MOAIDAuthConstants.SLOSTATUS_ERROR;
+
 									}
 									transactionStorage.put(artifact, statusCode, -1);
-							        redirectURL = addURLParameter(redirectURL, MOAIDAuthConstants.PARAM_SLOSTATUS, artifact);
-							        
+									redirectURL = addURLParameter(redirectURL, MOAIDAuthConstants.PARAM_SLOSTATUS, artifact);
+
 								}								
 								//redirect to Redirect Servlet
 								String url = req.getAuthURL() + "/RedirectServlet";
 								url = addURLParameter(url, RedirectServlet.REDIRCT_PARAM_URL, URLEncoder.encode(redirectURL, "UTF-8"));
 								url = httpResp.encodeRedirectURL(url);
-							
+
 								httpResp.setContentType("text/html");
 								httpResp.setStatus(302);
 								httpResp.addHeader("Location", url);
-		
+
 							}
 						} else {
 							Logger.warn("Sessioninformation Cast-Exception by using Artifact=" + relayState);
 							throw new MOADatabaseException("Sessioninformation Cast-Exception");
-						
+
 						}						
 					}
-					
-				} catch (MOADatabaseException e) {
-					Logger.error("MOA AssertionDatabase ERROR", e);
-					throw new SLOException("pvp2.19", null);
-					
-				} catch (UnsupportedEncodingException e) {
-					Logger.error("Finale SLO redirct not possible.", e);
-					throw new AuthenticationException("pvp2.13", new Object[]{});
-
-				} finally {
-					if (tx != null && !tx.getStatus().equals(TransactionStatus.COMMITTED)) {
-						tx.commit();
-						
-					}
 				}
-				
-				
-							
-			} else {
-				Logger.error("Process SingleLogOutAction but request is NOT of type LogoutRequest or LogoutResponse.");
-				throw new MOAIDException("pvp2.13", null);
-				
-			}
-							
+			} catch (MOADatabaseException e) {
+				Logger.error("MOA AssertionDatabase ERROR", e);
+				throw new SLOException("pvp2.19", null);
+
+			} catch (UnsupportedEncodingException e) {
+				Logger.error("Finale SLO redirct not possible.", e);
+				throw new AuthenticationException("pvp2.13", new Object[]{});
+
+			} 
+
+			//				finally {
+			//					if (tx != null && !tx.getStatus().equals(TransactionStatus.COMMITTED)) {
+			//						tx.commit();
+			//						
+			//					}
+			//				}
+
+
+
+		} else {
+			Logger.error("Process SingleLogOutAction but request is NOT of type LogoutRequest or LogoutResponse.");
+			throw new MOAIDException("pvp2.13", null);
+
+		}
+
 		return null;		
 	}
 
@@ -317,7 +325,7 @@ public class SingleLogOutAction implements IAction {
 	public String getDefaultActionName() {
 		return PVP2XProtocol.SINGLELOGOUT;
 	}
-	
+
 	protected static String addURLParameter(String url, String paramname,
 			String paramvalue) {
 		String param = paramname + "=" + paramvalue;
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/DBTransactionStorage.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/DBTransactionStorage.java
index 89df47615..fa8ca8547 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/DBTransactionStorage.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/DBTransactionStorage.java
@@ -104,7 +104,11 @@ public class DBTransactionStorage implements ITransactionStorage {
 			Logger.error("This exeption should not occur!!!!", e);
 			return null;
 			
-		}
+		}	
+	}
+	
+	public Object getAssertionStore(String key) throws MOADatabaseException{
+		return searchInDatabase(key);
 	}
 	
 	public Object get(String key) throws MOADatabaseException {
@@ -260,4 +264,11 @@ public class DBTransactionStorage implements ITransactionStorage {
 		
 	}
 
+	@Override
+	public void putAssertionStore(Object element) throws MOADatabaseException{
+		// TODO Auto-generated method stub
+		entityManager.merge(element);
+		
+	}
+
 }
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/ITransactionStorage.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/ITransactionStorage.java
index 4651566fc..53a7f4f5e 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/ITransactionStorage.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/ITransactionStorage.java
@@ -111,4 +111,21 @@ public interface ITransactionStorage {
 	 */
 	public List<String> clean(Date now, long dataTimeOut);
 	
+	
+	/**
+	 * Get whole AssertionStoreObject, required for SLO
+	 * 
+	 * @param key key Id which identifiers the data object
+	 * @return The transaction-data object, or null
+	 * @throws MOADatabaseException In case of load operation failed
+	 */
+	public Object getAssertionStore(String key) throws MOADatabaseException;
+	
+	/**
+	 * Put whole AssertionStoreObject to db, required for SLO
+	 * 
+	 * @param element assertion store object
+	 */
+	public void putAssertionStore(Object element) throws MOADatabaseException;
+	
 }
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/RedisTransactionStorage.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/RedisTransactionStorage.java
index cae73fafd..c17bff358 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/RedisTransactionStorage.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/RedisTransactionStorage.java
@@ -352,4 +352,26 @@ private AssertionStore prepareAssertion(AssertionStore element, String key, Obje
 		
 	}
 
+@Override
+public Object getAssertionStore(String key) throws MOADatabaseException {
+	return searchInDatabase(key);
+}
+
+@Override
+public void putAssertionStore(Object element) throws MOADatabaseException {
+	// TODO Auto-generated method stub
+	AssertionStore as = (AssertionStore)element;
+	final int expTime = redisTemplate.getExpire(as.getArtifact(), TimeUnit.MILLISECONDS).intValue();
+	//AssertionStore element = searchInDatabase(oldKey);		
+	if (expTime < 0) {
+		Logger.info("No transaction-data with oldKey:" + as.getArtifact()
+				+ " found. Process gets stopped.");
+		throw new MOADatabaseException("No transaction-data with oldKey:" + as.getArtifact()
+				+ " found. Process gets stopped.");
+		
+	}
+	redisTemplate.opsForValue().set(as.getArtifact(), new String(assertionStoreSerializer.serialize(element)),expTime,TimeUnit.MILLISECONDS);
+	
+}
+
 }
-- 
cgit v1.2.3