From d2e13a634df6f61d1d1280e4a6d2523bc2069203 Mon Sep 17 00:00:00 2001 From: felmer <felmer> Date: Tue, 9 Sep 2008 07:27:56 +0000 Subject: [PATCH] LMS-445 GenericServer with authentication and session management implemented SVN: 8241 --- .../web/client/IGenericClientService.java | 5 + .../client/IGenericClientServiceAsync.java | 4 + .../client/web/client/dto/SessionContext.java | 11 ++ .../web/server/GenericClientService.java | 105 +++++++++++++++++- .../server/GenericClientServiceServlet.java | 6 +- .../generic/genericApplicationContext.xml | 12 +- .../cisd/openbis/generic/server/.gitignore | 0 .../openbis/generic/server/GenericServer.java | 70 ++++++++++++ .../server/LogMessagePrefixGenerator.java | 64 +++++++++++ .../generic/server/SessionFactory.java | 38 +++++++ .../generic/shared/IGenericServer.java | 33 ++++++ .../openbis/generic/shared/dto/Session.java | 64 +++++++++++ openbis/source/java/service.properties | 4 + 13 files changed, 406 insertions(+), 10 deletions(-) delete mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/server/.gitignore create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/server/GenericServer.java create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/server/LogMessagePrefixGenerator.java create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/server/SessionFactory.java create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IGenericServer.java create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/Session.java diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/IGenericClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/IGenericClientService.java index 443894824b0..71d218bc323 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/IGenericClientService.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/IGenericClientService.java @@ -42,4 +42,9 @@ public interface IGenericClientService extends RemoteService * Tries to login with specified user ID and password. If failed <code>null</code> is returned. */ public SessionContext tryToLogin(String userID, String password); + + /** + * Logs out. + */ + public void logout(); } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/IGenericClientServiceAsync.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/IGenericClientServiceAsync.java index 710474a2570..c715a9a43e9 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/IGenericClientServiceAsync.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/IGenericClientServiceAsync.java @@ -36,4 +36,8 @@ public interface IGenericClientServiceAsync /** @see IGenericClientService#tryToLogin(String, String) */ public void tryToLogin(String userID, String password, AsyncCallback<SessionContext> callback); + + /** @see IGenericClientService#logout() */ + public void logout(AsyncCallback<Void> callback); + } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/SessionContext.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/SessionContext.java index bf4570e1252..97eb387a273 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/SessionContext.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/SessionContext.java @@ -26,6 +26,7 @@ import com.google.gwt.user.client.rpc.IsSerializable; public class SessionContext implements IsSerializable { private User user; + private String sessionID; public final User getUser() { @@ -36,4 +37,14 @@ public class SessionContext implements IsSerializable { this.user = user; } + + public final String getSessionID() + { + return sessionID; + } + + public final void setSessionID(String sessionID) + { + this.sessionID = sessionID; + } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientService.java index 59f4530d253..91c2c8c95ae 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientService.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientService.java @@ -16,10 +16,23 @@ package ch.systemsx.cisd.openbis.generic.client.web.server; +import javax.servlet.http.HttpSession; + +import org.apache.log4j.Logger; + +import ch.systemsx.cisd.common.exceptions.InvalidSessionException; +import ch.systemsx.cisd.common.logging.LogCategory; +import ch.systemsx.cisd.common.logging.LogFactory; +import ch.systemsx.cisd.common.servlet.IRequestContextProvider; import ch.systemsx.cisd.common.utilities.BuildAndEnvironmentInfo; +import ch.systemsx.cisd.lims.base.dto.GroupPE; +import ch.systemsx.cisd.lims.base.dto.PersonPE; import ch.systemsx.cisd.openbis.generic.client.web.client.IGenericClientService; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ApplicationInfo; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.SessionContext; +import ch.systemsx.cisd.openbis.generic.client.web.client.dto.User; +import ch.systemsx.cisd.openbis.generic.shared.IGenericServer; +import ch.systemsx.cisd.openbis.generic.shared.dto.Session; /** * @@ -28,10 +41,69 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.SessionContext; */ public class GenericClientService implements IGenericClientService { + private static final String SESSION_KEY = "openbis-session"; + + private static final Logger operationLog = + LogFactory.getLogger(LogCategory.OPERATION, GenericClientService.class); + + private final IGenericServer server; + private final IRequestContextProvider requestContextProvider; + + public GenericClientService(final IGenericServer server, + final IRequestContextProvider requestContextProvider) + { + this.server = server; + this.requestContextProvider = requestContextProvider; + } + void setConfigParameters(GenericConfigParameters configParameters) { } + private SessionContext createSessionContext(final Session session) + { + SessionContext sessionContext = new SessionContext(); + sessionContext.setSessionID(session.getSessionToken()); + User user = new User(); + user.setUserName(session.getUserName()); + PersonPE person = session.tryToGetPerson(); + if (person != null) + { + GroupPE homeGroup = person.getHomeGroup(); + if (homeGroup != null) + { + user.setHomeGroupCode(homeGroup.getCode()); + } + } + sessionContext.setUser(user); + return sessionContext; + } + + private Session getSession(final HttpSession httpSession) + { + Session session = (Session) httpSession.getAttribute(SESSION_KEY); + if (session == null) + { + final String remoteHost = + requestContextProvider.getHttpServletRequest().getRemoteHost(); + final String msg = + "Attempt to get non-existent session from host '" + remoteHost + + "': user is not logged in."; + if (operationLog.isInfoEnabled()) + { + operationLog.info(msg); + } + throw new InvalidSessionException(msg); + + } + return session; + } + + private HttpSession getOrCreateHttpSession(boolean create) + { + return requestContextProvider.getHttpServletRequest().getSession(create); + } + public ApplicationInfo getApplicationInfo() { ApplicationInfo applicationInfo = new ApplicationInfo(); @@ -41,14 +113,39 @@ public class GenericClientService implements IGenericClientService public SessionContext tryToGetCurrentSessionContext() { - // TODO Auto-generated method stub - return null; + final HttpSession httpSession = getOrCreateHttpSession(false); + if (httpSession == null) + { + return null; + } + final Session session = getSession(httpSession); + return createSessionContext(session); } public SessionContext tryToLogin(String userID, String password) { - // TODO Auto-generated method stub - return null; + Session session = server.tryToAuthenticate(userID, password); + if (session == null) + { + return null; + } + HttpSession httpSession = getOrCreateHttpSession(true); + // Expiration time of httpSession is 10 seconds less than of session + httpSession.setMaxInactiveInterval(session.getSessionExpirationTime() / 1000 - 10); + httpSession.setAttribute(SESSION_KEY, session); + return createSessionContext(session); + } + + public void logout() + { + HttpSession httpSession = getOrCreateHttpSession(false); + if (httpSession != null) + { + Session session = getSession(httpSession); + httpSession.removeAttribute(SESSION_KEY); + httpSession.invalidate(); + server.logout(session.getSessionToken()); + } } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientServiceServlet.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientServiceServlet.java index 2d2cf6df20b..bb026a18cfc 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientServiceServlet.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientServiceServlet.java @@ -95,7 +95,6 @@ public class GenericClientServiceServlet extends GWTSpringController implements public ApplicationInfo getApplicationInfo() { - operationLog.info("getApplicationInfo()"); return service.getApplicationInfo(); } @@ -109,4 +108,9 @@ public class GenericClientServiceServlet extends GWTSpringController implements return service.tryToLogin(userID, password); } + public void logout() + { + service.logout(); + } + } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/genericApplicationContext.xml b/openbis/source/java/ch/systemsx/cisd/openbis/generic/genericApplicationContext.xml index 184b4199b97..f3f4a5c4927 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/genericApplicationContext.xml +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/genericApplicationContext.xml @@ -12,14 +12,16 @@ --> <bean id="generic-service" class="ch.systemsx.cisd.openbis.generic.client.web.server.GenericClientService"> - <!-- constructor-arg ref="${authentication-service}" /> + <constructor-arg ref="generic-server" /> <constructor-arg ref="request-context-provider" /> - <constructor-arg ref="console-factory" /> - <constructor-arg ref="action-log" /> - <property name="sessionExpirationPeriodInMinutes" value="${session-timeout}" /--> </bean> - <bean id="action-log" class="ch.systemsx.cisd.openbis.generic.client.web.server.GenericActionLog"> + <bean id="generic-server" class="ch.systemsx.cisd.openbis.generic.server.GenericServer"> + <constructor-arg ref="${authentication-service}" /> + <constructor-arg ref="request-context-provider" /> + <!-- The time after which an inactive session is expired by the service (in minutes). --> + <constructor-arg value="${session-timeout}" /> </bean> + </beans> \ No newline at end of file diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/.gitignore b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/.gitignore deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/GenericServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/GenericServer.java new file mode 100644 index 00000000000..78a9be3ecf5 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/GenericServer.java @@ -0,0 +1,70 @@ +/* + * Copyright 2008 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.generic.server; + +import ch.systemsx.cisd.authentication.DefaultSessionManager; +import ch.systemsx.cisd.authentication.IAuthenticationService; +import ch.systemsx.cisd.authentication.ISessionManager; +import ch.systemsx.cisd.common.servlet.IRequestContextProvider; +import ch.systemsx.cisd.common.servlet.RequestContextProviderAdapter; +import ch.systemsx.cisd.openbis.generic.shared.IGenericServer; +import ch.systemsx.cisd.openbis.generic.shared.dto.Session; + +/** + * + * + * @author Franz-Josef Elmer + */ +public class GenericServer implements IGenericServer +{ + private final ISessionManager<Session> sessionManager; + + public GenericServer(IAuthenticationService authenticationService, + IRequestContextProvider requestContextProvider, int sessionExpirationPeriodInMinutes) + { + this(new DefaultSessionManager<Session>(new SessionFactory(), + new LogMessagePrefixGenerator(), authenticationService, + new RequestContextProviderAdapter(requestContextProvider), + sessionExpirationPeriodInMinutes)); + } + + GenericServer(ISessionManager<Session> sessionManager) + { + this.sessionManager = sessionManager; + } + + public int getVersion() + { + return 1; + } + + public void logout(String sessionToken) + { + sessionManager.closeSession(sessionToken); + } + + public Session tryToAuthenticate(String user, String password) + { + String sessionToken = sessionManager.tryToOpenSession(user, password); + if (sessionToken == null) + { + return null; + } + return sessionManager.getSession(sessionToken); + } + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/LogMessagePrefixGenerator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/LogMessagePrefixGenerator.java new file mode 100644 index 00000000000..9e247f09247 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/LogMessagePrefixGenerator.java @@ -0,0 +1,64 @@ +/* + * Copyright 2008 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.generic.server; + +import ch.systemsx.cisd.authentication.ILogMessagePrefixGenerator; +import ch.systemsx.cisd.lims.base.dto.GroupPE; +import ch.systemsx.cisd.lims.base.dto.PersonPE; +import ch.systemsx.cisd.openbis.generic.shared.dto.Session; + +/** + * + * + * @author Franz-Josef Elmer + */ +class LogMessagePrefixGenerator implements ILogMessagePrefixGenerator<Session> +{ + + public String createPrefix(Session session) + { + String userName = session.getUserName(); + String groupCode = null; + PersonPE person = session.tryToGetPerson(); + if (person != null) + { + GroupPE homeGroup = person.getHomeGroup(); + if (homeGroup != null) + { + groupCode = homeGroup.getCode(); + } + } + String remoteHost = session.getRemoteHost(); + return createPrefix(userName, groupCode, remoteHost); + } + + public String createPrefix(String user, String remoteHost) + { + return createPrefix(user, null, remoteHost); + } + + private String createPrefix(String user, String groupCodeOrNull, String remoteHost) + { + return String.format("[USER:%s GROUP:%s HOST:%s]", cite(user), + cite(groupCodeOrNull), cite(remoteHost)); + } + + private String cite(final String text) + { + return text == null ? "<UNDEFINED>" : "'" + text + "'"; + } +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/SessionFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/SessionFactory.java new file mode 100644 index 00000000000..3d40db13169 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/SessionFactory.java @@ -0,0 +1,38 @@ +/* + * Copyright 2008 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.generic.server; + +import ch.systemsx.cisd.authentication.ISessionFactory; +import ch.systemsx.cisd.authentication.Principal; +import ch.systemsx.cisd.openbis.generic.shared.dto.Session; + +/** + * + * + * @author Franz-Josef Elmer + */ +class SessionFactory implements ISessionFactory<Session> +{ + + public Session create(String sessionToken, String userName, Principal principal, + String remoteHost, long sessionStart, int expirationTime) + { + return new Session(sessionToken, userName, principal, remoteHost, sessionStart, + expirationTime); + } + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IGenericServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IGenericServer.java new file mode 100644 index 00000000000..88e89d4c766 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IGenericServer.java @@ -0,0 +1,33 @@ +/* + * Copyright 2008 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.generic.shared; + +import ch.systemsx.cisd.openbis.generic.shared.dto.Session; + +/** + * + * + * @author Franz-Josef Elmer + */ +public interface IGenericServer +{ + public int getVersion(); + + public Session tryToAuthenticate(String user, String password); + + public void logout(String sessionToken); +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/Session.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/Session.java new file mode 100644 index 00000000000..93e2ce09e08 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/Session.java @@ -0,0 +1,64 @@ +/* + * Copyright 2008 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.generic.shared.dto; + +import org.apache.commons.lang.time.DateFormatUtils; + +import ch.systemsx.cisd.authentication.BasicSession; +import ch.systemsx.cisd.authentication.Principal; +import ch.systemsx.cisd.lims.base.dto.PersonPE; + +/** + * + * + * @author Franz-Josef Elmer + */ +public class Session extends BasicSession +{ + private static final long serialVersionUID = 1L; + + private PersonPE person; + + /** + * Creates a new instance. + */ + public Session(String sessionToken, String userName, Principal principal, String remoteHost, + long sessionStart, int expirationTime) + { + super(sessionToken, userName, principal, remoteHost, sessionStart, expirationTime); + } + + public final PersonPE tryToGetPerson() + { + return person; + } + + public final void setPerson(PersonPE person) + { + this.person = person; + } + + @Override + public final String toString() + { + return "Session{user=" + getUserName() + ",group=" + person.getHomeGroup() + ",remoteHost=" + + getRemoteHost() + ",sessionstart=" + + DateFormatUtils.format(getSessionStart(), DATE_FORMAT_PATTERN) + "}"; + } + + +} diff --git a/openbis/source/java/service.properties b/openbis/source/java/service.properties index e69de29bb2d..d51b73ae2dc 100644 --- a/openbis/source/java/service.properties +++ b/openbis/source/java/service.properties @@ -0,0 +1,4 @@ +authentication-service = dummy-authentication-service + +# The time after which an inactive session is expired by the service (in minutes). +session-timeout = 30 -- GitLab