From 42872b3d629a971c74aa4390d234dd9198bdd055 Mon Sep 17 00:00:00 2001 From: Gustavo Martin Morcuende Date: Tue, 4 Oct 2016 20:39:28 +0200 Subject: [PATCH] Renaming packages and using properties file with time out session value --- src/main/java/com/prueba/MainRun.java | 31 ++++++++ .../prueba/controllers/web/PagesController.java | 4 +- src/main/java/com/prueba/core/Handle.java | 12 ---- src/main/java/com/prueba/core/MainRun.java | 31 -------- .../prueba/core/context/handles/ApiHandler.java | 49 ------------- .../prueba/core/context/handles/LoginHandler.java | 46 ------------ .../prueba/core/context/handles/PagesHandler.java | 75 -------------------- .../core/context/handles/SessionHandler.java | 37 ---------- .../authenticator/CustomBasicAuthenticator.java | 28 -------- .../persistence/AuthenticationInfo.java | 13 ---- .../context/security/persistence/SessionInfo.java | 28 -------- .../context/security/persistence/Sessions.java | 56 --------------- .../context/BasicAuthenticationContext.java | 15 ---- .../persistence/context/SessionContext.java | 15 ---- .../web/application/ApplicationWebContext.java | 8 +-- .../http/authentication/AuthenticationInfo.java | 13 ++++ .../authentication/BasicAuthenticationContext.java | 13 ++++ .../authentication/CustomBasicAuthenticator.java | 26 +++++++ .../com/prueba/core/http/handles/ApiHandler.java | 49 +++++++++++++ .../java/com/prueba/core/http/handles/Handle.java | 12 ++++ .../com/prueba/core/http/handles/LoginHandler.java | 46 ++++++++++++ .../com/prueba/core/http/handles/PagesHandler.java | 75 ++++++++++++++++++++ .../prueba/core/http/handles/SessionHandler.java | 37 ++++++++++ .../prueba/core/http/sessions/SessionContext.java | 13 ++++ .../com/prueba/core/http/sessions/SessionInfo.java | 28 ++++++++ .../com/prueba/core/http/sessions/Sessions.java | 82 ++++++++++++++++++++++ .../com/prueba/services/impl/LoginServiceImpl.java | 6 +- src/main/resources/prueba.properties | 2 + .../security/persistence/SessionInfoTest.java | 24 ------- .../prueba/core/http/sessions/SessionInfoTest.java | 24 +++++++ 30 files changed, 460 insertions(+), 438 deletions(-) create mode 100644 src/main/java/com/prueba/MainRun.java delete mode 100644 src/main/java/com/prueba/core/Handle.java delete mode 100644 src/main/java/com/prueba/core/MainRun.java delete mode 100644 src/main/java/com/prueba/core/context/handles/ApiHandler.java delete mode 100644 src/main/java/com/prueba/core/context/handles/LoginHandler.java delete mode 100644 src/main/java/com/prueba/core/context/handles/PagesHandler.java delete mode 100644 src/main/java/com/prueba/core/context/handles/SessionHandler.java delete mode 100644 src/main/java/com/prueba/core/context/security/authenticator/CustomBasicAuthenticator.java delete mode 100644 src/main/java/com/prueba/core/context/security/authenticator/persistence/AuthenticationInfo.java delete mode 100644 src/main/java/com/prueba/core/context/security/persistence/SessionInfo.java delete mode 100644 src/main/java/com/prueba/core/context/security/persistence/Sessions.java delete mode 100644 src/main/java/com/prueba/core/context/security/persistence/context/BasicAuthenticationContext.java delete mode 100644 src/main/java/com/prueba/core/context/security/persistence/context/SessionContext.java create mode 100644 src/main/java/com/prueba/core/http/authentication/AuthenticationInfo.java create mode 100644 src/main/java/com/prueba/core/http/authentication/BasicAuthenticationContext.java create mode 100644 src/main/java/com/prueba/core/http/authentication/CustomBasicAuthenticator.java create mode 100644 src/main/java/com/prueba/core/http/handles/ApiHandler.java create mode 100644 src/main/java/com/prueba/core/http/handles/Handle.java create mode 100644 src/main/java/com/prueba/core/http/handles/LoginHandler.java create mode 100644 src/main/java/com/prueba/core/http/handles/PagesHandler.java create mode 100644 src/main/java/com/prueba/core/http/handles/SessionHandler.java create mode 100644 src/main/java/com/prueba/core/http/sessions/SessionContext.java create mode 100644 src/main/java/com/prueba/core/http/sessions/SessionInfo.java create mode 100644 src/main/java/com/prueba/core/http/sessions/Sessions.java create mode 100644 src/main/resources/prueba.properties delete mode 100644 src/test/java/com/prueba/core/context/security/persistence/SessionInfoTest.java create mode 100644 src/test/java/com/prueba/core/http/sessions/SessionInfoTest.java diff --git a/src/main/java/com/prueba/MainRun.java b/src/main/java/com/prueba/MainRun.java new file mode 100644 index 0000000..1af3fcb --- /dev/null +++ b/src/main/java/com/prueba/MainRun.java @@ -0,0 +1,31 @@ +package com.prueba; + +import java.io.IOException; +import java.net.InetSocketAddress; + +import com.prueba.core.context.ApplicationContext; +import com.prueba.core.context.web.application.ApplicationWebContext; +import com.prueba.core.http.authentication.CustomBasicAuthenticator; +import com.prueba.core.http.handles.ApiHandler; +import com.prueba.core.http.handles.LoginHandler; +import com.prueba.core.http.handles.PagesHandler; +import com.sun.net.httpserver.HttpContext; +import com.sun.net.httpserver.HttpServer; + +public class MainRun { + + public static void main(String[] args) throws IOException { + ApplicationContext appContext = ApplicationWebContext.getInstance(); + + HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0); + server.createContext(PagesHandler.CONTEXT, appContext.getWebHandler()); + server.createContext(LoginHandler.CONTEXT, appContext.getLoginHandler()); + + HttpContext apiContext = server.createContext(ApiHandler.CONTEXT, appContext.getApiHandler()); + apiContext.setAuthenticator(new CustomBasicAuthenticator(ApiHandler.CONTEXT)); + + server.setExecutor(null); + + server.start(); + } +} diff --git a/src/main/java/com/prueba/controllers/web/PagesController.java b/src/main/java/com/prueba/controllers/web/PagesController.java index cf9c8de..c420a52 100644 --- a/src/main/java/com/prueba/controllers/web/PagesController.java +++ b/src/main/java/com/prueba/controllers/web/PagesController.java @@ -4,8 +4,8 @@ import java.io.IOException; import java.io.OutputStream; import com.prueba.controllers.Controller; -import com.prueba.core.context.security.persistence.SessionInfo; -import com.prueba.core.context.security.persistence.context.SessionContext; +import com.prueba.core.http.sessions.SessionContext; +import com.prueba.core.http.sessions.SessionInfo; import com.prueba.view.page.PageImpl; import com.sun.net.httpserver.HttpExchange; diff --git a/src/main/java/com/prueba/core/Handle.java b/src/main/java/com/prueba/core/Handle.java deleted file mode 100644 index 67231a1..0000000 --- a/src/main/java/com/prueba/core/Handle.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.prueba.core; - -import com.sun.net.httpserver.HttpExchange; - -public interface Handle { - - /** - * Handle some HTTP request - * @param httpExchange the HTTP request - */ - public void handle(HttpExchange httpExchange); -} diff --git a/src/main/java/com/prueba/core/MainRun.java b/src/main/java/com/prueba/core/MainRun.java deleted file mode 100644 index 7169c09..0000000 --- a/src/main/java/com/prueba/core/MainRun.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.prueba.core; - -import java.io.IOException; -import java.net.InetSocketAddress; - -import com.prueba.core.context.ApplicationContext; -import com.prueba.core.context.handles.LoginHandler; -import com.prueba.core.context.handles.PagesHandler; -import com.prueba.core.context.security.authenticator.CustomBasicAuthenticator; -import com.prueba.core.context.handles.ApiHandler; -import com.prueba.core.context.web.application.ApplicationWebContext; -import com.sun.net.httpserver.HttpContext; -import com.sun.net.httpserver.HttpServer; - -public class MainRun { - - public static void main(String[] args) throws IOException { - ApplicationContext appContext = ApplicationWebContext.getInstance(); - - HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0); - server.createContext(PagesHandler.CONTEXT, appContext.getWebHandler()); - server.createContext(LoginHandler.CONTEXT, appContext.getLoginHandler()); - - HttpContext apiContext = server.createContext(ApiHandler.CONTEXT, appContext.getApiHandler()); - apiContext.setAuthenticator(new CustomBasicAuthenticator(ApiHandler.CONTEXT)); - - server.setExecutor(null); - - server.start(); - } -} diff --git a/src/main/java/com/prueba/core/context/handles/ApiHandler.java b/src/main/java/com/prueba/core/context/handles/ApiHandler.java deleted file mode 100644 index e7313f2..0000000 --- a/src/main/java/com/prueba/core/context/handles/ApiHandler.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.prueba.core.context.handles; - -import java.io.IOException; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.prueba.controllers.rest.ApiController; -import com.prueba.core.context.security.authenticator.persistence.AuthenticationInfo; -import com.prueba.core.context.security.persistence.context.BasicAuthenticationContext; -import com.prueba.services.impl.AuthorizationServicesImpl; -import com.sun.net.httpserver.HttpExchange; -import com.sun.net.httpserver.HttpHandler; - -public class ApiHandler implements HttpHandler { - public static final String CONTEXT = "/app/api/users/"; - - private static final Logger LOGGER = LoggerFactory.getLogger(ApiHandler.class); - - private final ApiController apiController = new ApiController(); - private final AuthorizationServicesImpl authorizationService = new AuthorizationServicesImpl(); - - @Override - public void handle(HttpExchange httpExchange) throws IOException { - - try { - this.handleThrowable(httpExchange); - } catch (Exception exception) { - LOGGER.error("ApiHandler error: ", exception); - - httpExchange.sendResponseHeaders(500, 0); - } finally { - httpExchange.close(); - } - } - - protected void handleThrowable(HttpExchange httpExchange) throws IOException { - AuthenticationInfo authenticationInfo = BasicAuthenticationContext.getAuthentication(); - - if(authorizationService.isAuthorized(httpExchange.getRequestMethod(), - httpExchange.getRequestURI().toString(), authenticationInfo.getUserName())) { - - apiController.handle(httpExchange); - - } else { - httpExchange.sendResponseHeaders(403, 0); - } - } -} diff --git a/src/main/java/com/prueba/core/context/handles/LoginHandler.java b/src/main/java/com/prueba/core/context/handles/LoginHandler.java deleted file mode 100644 index 423eb7b..0000000 --- a/src/main/java/com/prueba/core/context/handles/LoginHandler.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.prueba.core.context.handles; - -import java.io.IOException; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.prueba.controllers.web.LoginController; -import com.sun.net.httpserver.HttpExchange; -import com.sun.net.httpserver.HttpHandler; - - -public class LoginHandler implements HttpHandler { - public static final String CONTEXT = "/app/login/"; - public static final String LOGIN_PAGE = "/app/login/login.html?serviceName=http://localhost:8080"; - - private static final Logger LOGGER = LoggerFactory.getLogger(LoginHandler.class); - - - private final LoginController loginController = new LoginController(); - private final HttpHandler sessionHandler; - - public LoginHandler(HttpHandler sessionHandler) { - this.sessionHandler = sessionHandler; - } - - @Override - public void handle(HttpExchange httpExchange) throws IOException { - try { - this.handleThrowable(httpExchange); - } catch (Exception exception) { - LOGGER.error("LoginHandler error: ", exception); - - httpExchange.sendResponseHeaders(500, 0); - } finally { - httpExchange.close(); - } - - } - - protected void handleThrowable(HttpExchange httpExchange) throws IOException { - sessionHandler.handle(httpExchange); - - loginController.handle(httpExchange); - } -} diff --git a/src/main/java/com/prueba/core/context/handles/PagesHandler.java b/src/main/java/com/prueba/core/context/handles/PagesHandler.java deleted file mode 100644 index 468924b..0000000 --- a/src/main/java/com/prueba/core/context/handles/PagesHandler.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.prueba.core.context.handles; - -import java.io.IOException; -import java.net.URI; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.prueba.controllers.web.PagesController; -import com.prueba.core.context.security.persistence.SessionInfo; -import com.prueba.core.context.security.persistence.Sessions; -import com.prueba.core.context.security.persistence.context.SessionContext; -import com.prueba.services.impl.AuthorizationServicesImpl; -import com.sun.net.httpserver.Headers; -import com.sun.net.httpserver.HttpExchange; -import com.sun.net.httpserver.HttpHandler; - - -public class PagesHandler implements HttpHandler { - public static final String CONTEXT = "/app/pages/"; - - private static final Logger LOGGER = LoggerFactory.getLogger(PagesHandler.class); - private static final String SERVER_ADDRESS = "http://localhost:8080"; - - private final PagesController pagesController = new PagesController(); - private final AuthorizationServicesImpl authorizationService = new AuthorizationServicesImpl(); - private final HttpHandler sessionHandler; - - public PagesHandler(HttpHandler sessionHandler) { - this.sessionHandler = sessionHandler; - } - - @Override - public void handle(HttpExchange httpExchange) throws IOException { - try { - this.handleThrowable(httpExchange); - } catch (Exception exception) { - LOGGER.error("PagesHandler error: ", exception); - - httpExchange.sendResponseHeaders(500, 0); - } finally { - httpExchange.close(); - } - } - - protected void handleThrowable(HttpExchange httpExchange) throws IOException { - this.sessionHandler.handle(httpExchange); - - if (Sessions.getInstance().isValidSession(httpExchange)) { - final SessionInfo sessionInfo = SessionContext.getSession(); - - if(authorizationService.isAuthorized(httpExchange.getRequestMethod(), - httpExchange.getRequestURI().toString(), sessionInfo.getUsername())) { - - pagesController.handle(httpExchange); - - } else { - httpExchange.sendResponseHeaders(403, 0); - } - - Sessions.getInstance().refreshSession(sessionInfo.getUUID(), sessionInfo.getUsername()); - } else { - this.doRedirect(httpExchange); - } - } - - protected void doRedirect(HttpExchange httpExchange) throws IOException { - URI requestURI = httpExchange.getRequestURI(); - String requestURIString = requestURI.toString(); - Headers responseHeaders = httpExchange.getResponseHeaders(); - - responseHeaders.add("Location", SERVER_ADDRESS + LoginHandler.LOGIN_PAGE + requestURIString); - httpExchange.sendResponseHeaders(302, 0); - } -} diff --git a/src/main/java/com/prueba/core/context/handles/SessionHandler.java b/src/main/java/com/prueba/core/context/handles/SessionHandler.java deleted file mode 100644 index e84a94a..0000000 --- a/src/main/java/com/prueba/core/context/handles/SessionHandler.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.prueba.core.context.handles; - -import java.io.IOException; -import java.util.UUID; - -import com.prueba.core.context.security.persistence.SessionInfo; -import com.prueba.core.context.security.persistence.Sessions; -import com.prueba.core.context.security.persistence.context.SessionContext; -import com.sun.net.httpserver.Headers; -import com.sun.net.httpserver.HttpExchange; -import com.sun.net.httpserver.HttpHandler; - -public class SessionHandler implements HttpHandler { - private static final String COOKIE_HEADER = "Cookie"; - - - @Override - public void handle(HttpExchange httpExchange) throws IOException { - final SessionInfo sessionInfo = getSessionInfo(httpExchange); - - SessionContext.setSession(sessionInfo); - } - - protected SessionInfo getSessionInfo(HttpExchange httpExchange) { - final Headers headers = httpExchange.getRequestHeaders(); - final String cookieValue = headers.getFirst(COOKIE_HEADER); - - SessionInfo sessionInfo = null; - - if (cookieValue != null) { - final UUID uuid = UUID.fromString(cookieValue); - sessionInfo = Sessions.getInstance().getSession(uuid); - } - - return sessionInfo; - } -} diff --git a/src/main/java/com/prueba/core/context/security/authenticator/CustomBasicAuthenticator.java b/src/main/java/com/prueba/core/context/security/authenticator/CustomBasicAuthenticator.java deleted file mode 100644 index 2431825..0000000 --- a/src/main/java/com/prueba/core/context/security/authenticator/CustomBasicAuthenticator.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.prueba.core.context.security.authenticator; - -import com.prueba.core.context.security.authenticator.persistence.AuthenticationInfo; -import com.prueba.core.context.security.persistence.context.BasicAuthenticationContext; -import com.prueba.services.impl.LoginServiceImpl; -import com.sun.net.httpserver.BasicAuthenticator; - -public class CustomBasicAuthenticator extends BasicAuthenticator { - - public CustomBasicAuthenticator(String context) { - super(context); - } - - @Override - public boolean checkCredentials(String username, String password) { - final LoginServiceImpl loginService = new LoginServiceImpl(); - - if (loginService.isValidUser(username, password)) { - BasicAuthenticationContext.setAuthentication(new AuthenticationInfo(username)); - - return true; - } else { - BasicAuthenticationContext.setAuthentication(null); - - return false; - } - } -} diff --git a/src/main/java/com/prueba/core/context/security/authenticator/persistence/AuthenticationInfo.java b/src/main/java/com/prueba/core/context/security/authenticator/persistence/AuthenticationInfo.java deleted file mode 100644 index 78b8946..0000000 --- a/src/main/java/com/prueba/core/context/security/authenticator/persistence/AuthenticationInfo.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.prueba.core.context.security.authenticator.persistence; - -public class AuthenticationInfo { - private final String userName; - - public AuthenticationInfo(String userName) { - this.userName = userName; - } - - public String getUserName() { - return userName; - } -} diff --git a/src/main/java/com/prueba/core/context/security/persistence/SessionInfo.java b/src/main/java/com/prueba/core/context/security/persistence/SessionInfo.java deleted file mode 100644 index b629dab..0000000 --- a/src/main/java/com/prueba/core/context/security/persistence/SessionInfo.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.prueba.core.context.security.persistence; - -import java.time.LocalDateTime; -import java.util.UUID; - -public class SessionInfo { - private final UUID uuid; - private final String username; - private final LocalDateTime lastSessionTime; - - public SessionInfo(UUID uuid, String username, LocalDateTime lastSessionTime) { - this.uuid = uuid; - this.username = username; - this.lastSessionTime = lastSessionTime; - } - - public UUID getUUID() { - return uuid; - } - - public String getUsername() { - return username; - } - public LocalDateTime getLastSessionTime() { - return lastSessionTime; - } - -} diff --git a/src/main/java/com/prueba/core/context/security/persistence/Sessions.java b/src/main/java/com/prueba/core/context/security/persistence/Sessions.java deleted file mode 100644 index 416c296..0000000 --- a/src/main/java/com/prueba/core/context/security/persistence/Sessions.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.prueba.core.context.security.persistence; - -import java.time.LocalDateTime; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -import com.prueba.core.context.security.persistence.context.SessionContext; -import com.sun.net.httpserver.HttpExchange; - -public class Sessions { - private final Map sessions = new ConcurrentHashMap<>(); - - private Sessions() { - - } - - private static class SessionsContextHolder { - private static final Sessions INSTANCE = new Sessions(); - } - - public static Sessions getInstance() { - return SessionsContextHolder.INSTANCE; - } - - public SessionInfo getSession(UUID uuid) { - return sessions.get(uuid); - } - - public void refreshSession(UUID uuid, String username) { - final SessionInfo newSessionInfo = - new SessionInfo(uuid, username, LocalDateTime.now()); - sessions.put(uuid, newSessionInfo); - } - - public void removeSession(UUID uuid) { - sessions.remove(uuid); - } - - public boolean isValidSession(HttpExchange httpExchange) { - final SessionInfo sessionInfo = SessionContext.getSession(); - - boolean isValid = false; - - if (sessionInfo != null) { - LocalDateTime currentDateTime = LocalDateTime.now(); - if (sessionInfo.getLastSessionTime().plusMinutes(5).compareTo(currentDateTime) > 0) { - isValid = true; - } else { - sessions.remove(sessionInfo.getUUID()); - } - } - - return isValid; - } -} diff --git a/src/main/java/com/prueba/core/context/security/persistence/context/BasicAuthenticationContext.java b/src/main/java/com/prueba/core/context/security/persistence/context/BasicAuthenticationContext.java deleted file mode 100644 index 34203f3..0000000 --- a/src/main/java/com/prueba/core/context/security/persistence/context/BasicAuthenticationContext.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.prueba.core.context.security.persistence.context; - -import com.prueba.core.context.security.authenticator.persistence.AuthenticationInfo; - -public class BasicAuthenticationContext { - private static final ThreadLocal localContextSession = new ThreadLocal<>(); - - public static void setAuthentication(AuthenticationInfo authenticationInfo) { - localContextSession.set(authenticationInfo); - } - - public static AuthenticationInfo getAuthentication() { - return localContextSession.get(); - } -} diff --git a/src/main/java/com/prueba/core/context/security/persistence/context/SessionContext.java b/src/main/java/com/prueba/core/context/security/persistence/context/SessionContext.java deleted file mode 100644 index 6827ec8..0000000 --- a/src/main/java/com/prueba/core/context/security/persistence/context/SessionContext.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.prueba.core.context.security.persistence.context; - -import com.prueba.core.context.security.persistence.SessionInfo; - -public class SessionContext { - private static final ThreadLocal localContextSession = new ThreadLocal<>(); - - public static void setSession(SessionInfo sessionInfo) { - localContextSession.set(sessionInfo); - } - - public static SessionInfo getSession() { - return localContextSession.get(); - } -} diff --git a/src/main/java/com/prueba/core/context/web/application/ApplicationWebContext.java b/src/main/java/com/prueba/core/context/web/application/ApplicationWebContext.java index 1ab3604..c013494 100644 --- a/src/main/java/com/prueba/core/context/web/application/ApplicationWebContext.java +++ b/src/main/java/com/prueba/core/context/web/application/ApplicationWebContext.java @@ -3,12 +3,12 @@ package com.prueba.core.context.web.application; import javax.sql.DataSource; import com.prueba.core.context.ApplicationContext; -import com.prueba.core.context.handles.LoginHandler; -import com.prueba.core.context.handles.PagesHandler; -import com.prueba.core.context.handles.SessionHandler; import com.prueba.core.context.integration.datasource.impl.DoDataSourceContext; import com.prueba.core.context.integration.liquibase.impl.LiquibaseContext; -import com.prueba.core.context.handles.ApiHandler; +import com.prueba.core.http.handles.ApiHandler; +import com.prueba.core.http.handles.LoginHandler; +import com.prueba.core.http.handles.PagesHandler; +import com.prueba.core.http.handles.SessionHandler; import com.sun.net.httpserver.HttpHandler; diff --git a/src/main/java/com/prueba/core/http/authentication/AuthenticationInfo.java b/src/main/java/com/prueba/core/http/authentication/AuthenticationInfo.java new file mode 100644 index 0000000..3c3d277 --- /dev/null +++ b/src/main/java/com/prueba/core/http/authentication/AuthenticationInfo.java @@ -0,0 +1,13 @@ +package com.prueba.core.http.authentication; + +public class AuthenticationInfo { + private final String userName; + + public AuthenticationInfo(String userName) { + this.userName = userName; + } + + public String getUserName() { + return userName; + } +} diff --git a/src/main/java/com/prueba/core/http/authentication/BasicAuthenticationContext.java b/src/main/java/com/prueba/core/http/authentication/BasicAuthenticationContext.java new file mode 100644 index 0000000..631cdf8 --- /dev/null +++ b/src/main/java/com/prueba/core/http/authentication/BasicAuthenticationContext.java @@ -0,0 +1,13 @@ +package com.prueba.core.http.authentication; + +public class BasicAuthenticationContext { + private static final ThreadLocal localContextSession = new ThreadLocal<>(); + + public static void setAuthentication(AuthenticationInfo authenticationInfo) { + localContextSession.set(authenticationInfo); + } + + public static AuthenticationInfo getAuthentication() { + return localContextSession.get(); + } +} diff --git a/src/main/java/com/prueba/core/http/authentication/CustomBasicAuthenticator.java b/src/main/java/com/prueba/core/http/authentication/CustomBasicAuthenticator.java new file mode 100644 index 0000000..a7a72ce --- /dev/null +++ b/src/main/java/com/prueba/core/http/authentication/CustomBasicAuthenticator.java @@ -0,0 +1,26 @@ +package com.prueba.core.http.authentication; + +import com.prueba.services.impl.LoginServiceImpl; +import com.sun.net.httpserver.BasicAuthenticator; + +public class CustomBasicAuthenticator extends BasicAuthenticator { + + public CustomBasicAuthenticator(String context) { + super(context); + } + + @Override + public boolean checkCredentials(String username, String password) { + final LoginServiceImpl loginService = new LoginServiceImpl(); + + if (loginService.isValidUser(username, password)) { + BasicAuthenticationContext.setAuthentication(new AuthenticationInfo(username)); + + return true; + } else { + BasicAuthenticationContext.setAuthentication(null); + + return false; + } + } +} diff --git a/src/main/java/com/prueba/core/http/handles/ApiHandler.java b/src/main/java/com/prueba/core/http/handles/ApiHandler.java new file mode 100644 index 0000000..779bce7 --- /dev/null +++ b/src/main/java/com/prueba/core/http/handles/ApiHandler.java @@ -0,0 +1,49 @@ +package com.prueba.core.http.handles; + +import java.io.IOException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.prueba.controllers.rest.ApiController; +import com.prueba.core.http.authentication.AuthenticationInfo; +import com.prueba.core.http.authentication.BasicAuthenticationContext; +import com.prueba.services.impl.AuthorizationServicesImpl; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; + +public class ApiHandler implements HttpHandler { + public static final String CONTEXT = "/app/api/users/"; + + private static final Logger LOGGER = LoggerFactory.getLogger(ApiHandler.class); + + private final ApiController apiController = new ApiController(); + private final AuthorizationServicesImpl authorizationService = new AuthorizationServicesImpl(); + + @Override + public void handle(HttpExchange httpExchange) throws IOException { + + try { + this.handleThrowable(httpExchange); + } catch (Exception exception) { + LOGGER.error("ApiHandler error: ", exception); + + httpExchange.sendResponseHeaders(500, 0); + } finally { + httpExchange.close(); + } + } + + protected void handleThrowable(HttpExchange httpExchange) throws IOException { + AuthenticationInfo authenticationInfo = BasicAuthenticationContext.getAuthentication(); + + if(authorizationService.isAuthorized(httpExchange.getRequestMethod(), + httpExchange.getRequestURI().toString(), authenticationInfo.getUserName())) { + + apiController.handle(httpExchange); + + } else { + httpExchange.sendResponseHeaders(403, 0); + } + } +} diff --git a/src/main/java/com/prueba/core/http/handles/Handle.java b/src/main/java/com/prueba/core/http/handles/Handle.java new file mode 100644 index 0000000..9879562 --- /dev/null +++ b/src/main/java/com/prueba/core/http/handles/Handle.java @@ -0,0 +1,12 @@ +package com.prueba.core.http.handles; + +import com.sun.net.httpserver.HttpExchange; + +public interface Handle { + + /** + * Handle some HTTP request + * @param httpExchange the HTTP request + */ + public void handle(HttpExchange httpExchange); +} diff --git a/src/main/java/com/prueba/core/http/handles/LoginHandler.java b/src/main/java/com/prueba/core/http/handles/LoginHandler.java new file mode 100644 index 0000000..cfdd693 --- /dev/null +++ b/src/main/java/com/prueba/core/http/handles/LoginHandler.java @@ -0,0 +1,46 @@ +package com.prueba.core.http.handles; + +import java.io.IOException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.prueba.controllers.web.LoginController; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; + + +public class LoginHandler implements HttpHandler { + public static final String CONTEXT = "/app/login/"; + public static final String LOGIN_PAGE = "/app/login/login.html?serviceName=http://localhost:8080"; + + private static final Logger LOGGER = LoggerFactory.getLogger(LoginHandler.class); + + + private final LoginController loginController = new LoginController(); + private final HttpHandler sessionHandler; + + public LoginHandler(HttpHandler sessionHandler) { + this.sessionHandler = sessionHandler; + } + + @Override + public void handle(HttpExchange httpExchange) throws IOException { + try { + this.handleThrowable(httpExchange); + } catch (Exception exception) { + LOGGER.error("LoginHandler error: ", exception); + + httpExchange.sendResponseHeaders(500, 0); + } finally { + httpExchange.close(); + } + + } + + protected void handleThrowable(HttpExchange httpExchange) throws IOException { + sessionHandler.handle(httpExchange); + + loginController.handle(httpExchange); + } +} diff --git a/src/main/java/com/prueba/core/http/handles/PagesHandler.java b/src/main/java/com/prueba/core/http/handles/PagesHandler.java new file mode 100644 index 0000000..0a526d5 --- /dev/null +++ b/src/main/java/com/prueba/core/http/handles/PagesHandler.java @@ -0,0 +1,75 @@ +package com.prueba.core.http.handles; + +import java.io.IOException; +import java.net.URI; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.prueba.controllers.web.PagesController; +import com.prueba.core.http.sessions.SessionContext; +import com.prueba.core.http.sessions.SessionInfo; +import com.prueba.core.http.sessions.Sessions; +import com.prueba.services.impl.AuthorizationServicesImpl; +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; + + +public class PagesHandler implements HttpHandler { + public static final String CONTEXT = "/app/pages/"; + + private static final Logger LOGGER = LoggerFactory.getLogger(PagesHandler.class); + private static final String SERVER_ADDRESS = "http://localhost:8080"; + + private final PagesController pagesController = new PagesController(); + private final AuthorizationServicesImpl authorizationService = new AuthorizationServicesImpl(); + private final HttpHandler sessionHandler; + + public PagesHandler(HttpHandler sessionHandler) { + this.sessionHandler = sessionHandler; + } + + @Override + public void handle(HttpExchange httpExchange) throws IOException { + try { + this.handleThrowable(httpExchange); + } catch (Exception exception) { + LOGGER.error("PagesHandler error: ", exception); + + httpExchange.sendResponseHeaders(500, 0); + } finally { + httpExchange.close(); + } + } + + protected void handleThrowable(HttpExchange httpExchange) throws IOException { + this.sessionHandler.handle(httpExchange); + + if (Sessions.getInstance().isValidSession(httpExchange)) { + final SessionInfo sessionInfo = SessionContext.getSession(); + + if(authorizationService.isAuthorized(httpExchange.getRequestMethod(), + httpExchange.getRequestURI().toString(), sessionInfo.getUsername())) { + + pagesController.handle(httpExchange); + + } else { + httpExchange.sendResponseHeaders(403, 0); + } + + Sessions.getInstance().refreshSession(sessionInfo.getUUID(), sessionInfo.getUsername()); + } else { + this.doRedirect(httpExchange); + } + } + + protected void doRedirect(HttpExchange httpExchange) throws IOException { + URI requestURI = httpExchange.getRequestURI(); + String requestURIString = requestURI.toString(); + Headers responseHeaders = httpExchange.getResponseHeaders(); + + responseHeaders.add("Location", SERVER_ADDRESS + LoginHandler.LOGIN_PAGE + requestURIString); + httpExchange.sendResponseHeaders(302, 0); + } +} diff --git a/src/main/java/com/prueba/core/http/handles/SessionHandler.java b/src/main/java/com/prueba/core/http/handles/SessionHandler.java new file mode 100644 index 0000000..fbe6643 --- /dev/null +++ b/src/main/java/com/prueba/core/http/handles/SessionHandler.java @@ -0,0 +1,37 @@ +package com.prueba.core.http.handles; + +import java.io.IOException; +import java.util.UUID; + +import com.prueba.core.http.sessions.SessionContext; +import com.prueba.core.http.sessions.SessionInfo; +import com.prueba.core.http.sessions.Sessions; +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; + +public class SessionHandler implements HttpHandler { + private static final String COOKIE_HEADER = "Cookie"; + + + @Override + public void handle(HttpExchange httpExchange) throws IOException { + final SessionInfo sessionInfo = getSessionInfo(httpExchange); + + SessionContext.setSession(sessionInfo); + } + + protected SessionInfo getSessionInfo(HttpExchange httpExchange) { + final Headers headers = httpExchange.getRequestHeaders(); + final String cookieValue = headers.getFirst(COOKIE_HEADER); + + SessionInfo sessionInfo = null; + + if (cookieValue != null) { + final UUID uuid = UUID.fromString(cookieValue); + sessionInfo = Sessions.getInstance().getSession(uuid); + } + + return sessionInfo; + } +} diff --git a/src/main/java/com/prueba/core/http/sessions/SessionContext.java b/src/main/java/com/prueba/core/http/sessions/SessionContext.java new file mode 100644 index 0000000..95f900f --- /dev/null +++ b/src/main/java/com/prueba/core/http/sessions/SessionContext.java @@ -0,0 +1,13 @@ +package com.prueba.core.http.sessions; + +public class SessionContext { + private static final ThreadLocal localContextSession = new ThreadLocal<>(); + + public static void setSession(SessionInfo sessionInfo) { + localContextSession.set(sessionInfo); + } + + public static SessionInfo getSession() { + return localContextSession.get(); + } +} diff --git a/src/main/java/com/prueba/core/http/sessions/SessionInfo.java b/src/main/java/com/prueba/core/http/sessions/SessionInfo.java new file mode 100644 index 0000000..38a422a --- /dev/null +++ b/src/main/java/com/prueba/core/http/sessions/SessionInfo.java @@ -0,0 +1,28 @@ +package com.prueba.core.http.sessions; + +import java.time.LocalDateTime; +import java.util.UUID; + +public class SessionInfo { + private final UUID uuid; + private final String username; + private final LocalDateTime lastSessionTime; + + public SessionInfo(UUID uuid, String username, LocalDateTime lastSessionTime) { + this.uuid = uuid; + this.username = username; + this.lastSessionTime = lastSessionTime; + } + + public UUID getUUID() { + return uuid; + } + + public String getUsername() { + return username; + } + public LocalDateTime getLastSessionTime() { + return lastSessionTime; + } + +} diff --git a/src/main/java/com/prueba/core/http/sessions/Sessions.java b/src/main/java/com/prueba/core/http/sessions/Sessions.java new file mode 100644 index 0000000..1ac93e4 --- /dev/null +++ b/src/main/java/com/prueba/core/http/sessions/Sessions.java @@ -0,0 +1,82 @@ +package com.prueba.core.http.sessions; + +import java.io.IOException; +import java.io.InputStream; +import java.time.LocalDateTime; +import java.util.Map; +import java.util.Properties; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.net.httpserver.HttpExchange; + +public class Sessions { + private static final Logger LOGGER = LoggerFactory.getLogger(Sessions.class); + + private final Long sessionTimeout; + + private final Map sessions = new ConcurrentHashMap<>(); + + private Sessions() { + final Properties properties = this.loadProperties(); + + sessionTimeout = Long.valueOf(properties.getProperty("session.expire")); + } + + private static class SessionsContextHolder { + private static final Sessions INSTANCE = new Sessions(); + } + + public static Sessions getInstance() { + return SessionsContextHolder.INSTANCE; + } + + public SessionInfo getSession(UUID uuid) { + return sessions.get(uuid); + } + + public void refreshSession(UUID uuid, String username) { + final SessionInfo newSessionInfo = + new SessionInfo(uuid, username, LocalDateTime.now()); + sessions.put(uuid, newSessionInfo); + } + + public void removeSession(UUID uuid) { + sessions.remove(uuid); + } + + public boolean isValidSession(HttpExchange httpExchange) { + final SessionInfo sessionInfo = SessionContext.getSession(); + + boolean isValid = false; + + if (sessionInfo != null) { + final LocalDateTime currentDateTime = LocalDateTime.now(); + if (sessionInfo + .getLastSessionTime().plusMinutes(sessionTimeout).compareTo(currentDateTime) > 0) { + isValid = true; + } else { + sessions.remove(sessionInfo.getUUID()); + } + } + + return isValid; + } + + private Properties loadProperties() { + final Properties properties = new Properties(); + + try(final InputStream in = this.getClass().getResourceAsStream("/prueba.properties")) { + properties.load(in); + } catch (IOException exception) { + LOGGER.error("Load properties file error: ", exception); + + throw new IllegalStateException("Load properties file error", exception); + } + + return properties; + } +} diff --git a/src/main/java/com/prueba/services/impl/LoginServiceImpl.java b/src/main/java/com/prueba/services/impl/LoginServiceImpl.java index ecb9a49..495e8de 100644 --- a/src/main/java/com/prueba/services/impl/LoginServiceImpl.java +++ b/src/main/java/com/prueba/services/impl/LoginServiceImpl.java @@ -7,9 +7,9 @@ import java.io.OutputStream; import java.nio.charset.Charset; import java.util.UUID; -import com.prueba.core.context.security.persistence.SessionInfo; -import com.prueba.core.context.security.persistence.Sessions; -import com.prueba.core.context.security.persistence.context.SessionContext; +import com.prueba.core.http.sessions.SessionContext; +import com.prueba.core.http.sessions.SessionInfo; +import com.prueba.core.http.sessions.Sessions; import com.prueba.model.dao.AccountDao; import com.prueba.view.login.LoginFormImpl; import com.sun.net.httpserver.Headers; diff --git a/src/main/resources/prueba.properties b/src/main/resources/prueba.properties new file mode 100644 index 0000000..0bad532 --- /dev/null +++ b/src/main/resources/prueba.properties @@ -0,0 +1,2 @@ +# Session expire timeout in minutes +session.expire = 5 \ No newline at end of file diff --git a/src/test/java/com/prueba/core/context/security/persistence/SessionInfoTest.java b/src/test/java/com/prueba/core/context/security/persistence/SessionInfoTest.java deleted file mode 100644 index a158e1c..0000000 --- a/src/test/java/com/prueba/core/context/security/persistence/SessionInfoTest.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.prueba.core.context.security.persistence; - -import static org.junit.Assert.*; - -import java.time.LocalDateTime; -import java.util.UUID; - -import org.junit.Test; - -public class SessionInfoTest { - private static final UUID UUID_VALUE = UUID.randomUUID(); - private static final String USERNAME = "GUMARTINM"; - private static final LocalDateTime LAST_SESSION = LocalDateTime.now(); - - @Test - public void shouldCallGetters() { - SessionInfo sessionInfo = new SessionInfo(UUID_VALUE, USERNAME, LAST_SESSION); - - assertEquals(UUID_VALUE, sessionInfo.getUUID()); - assertEquals(USERNAME, sessionInfo.getUsername()); - assertEquals(LAST_SESSION, sessionInfo.getLastSessionTime()); - } - -} diff --git a/src/test/java/com/prueba/core/http/sessions/SessionInfoTest.java b/src/test/java/com/prueba/core/http/sessions/SessionInfoTest.java new file mode 100644 index 0000000..6f3e776 --- /dev/null +++ b/src/test/java/com/prueba/core/http/sessions/SessionInfoTest.java @@ -0,0 +1,24 @@ +package com.prueba.core.http.sessions; + +import static org.junit.Assert.*; + +import java.time.LocalDateTime; +import java.util.UUID; + +import org.junit.Test; + +public class SessionInfoTest { + private static final UUID UUID_VALUE = UUID.randomUUID(); + private static final String USERNAME = "GUMARTINM"; + private static final LocalDateTime LAST_SESSION = LocalDateTime.now(); + + @Test + public void shouldCallGetters() { + SessionInfo sessionInfo = new SessionInfo(UUID_VALUE, USERNAME, LAST_SESSION); + + assertEquals(UUID_VALUE, sessionInfo.getUUID()); + assertEquals(USERNAME, sessionInfo.getUsername()); + assertEquals(LAST_SESSION, sessionInfo.getLastSessionTime()); + } + +} -- 2.1.4