diff --git a/src/main/java/com/moandjiezana/tent/essayist/EssayistSession.java b/src/main/java/com/moandjiezana/tent/essayist/EssayistSession.java index 87fad4c..8c7bc80 100644 --- a/src/main/java/com/moandjiezana/tent/essayist/EssayistSession.java +++ b/src/main/java/com/moandjiezana/tent/essayist/EssayistSession.java @@ -3,6 +3,9 @@ package com.moandjiezana.tent.essayist; import com.google.inject.servlet.SessionScoped; import com.moandjiezana.tent.client.posts.Post; +import javax.inject.Inject; +import javax.servlet.http.HttpSession; + @SessionScoped public class EssayistSession { @@ -13,6 +16,13 @@ public class EssayistSession { }; private User user = LOGGED_OUT; + + private HttpSession httpSession; + + @Inject + public EssayistSession(HttpSession httpSession) { + this.httpSession = httpSession; + } public boolean isLoggedIn() { return getUser() != LOGGED_OUT; @@ -23,6 +33,7 @@ public class EssayistSession { } public void setUser(User user) { - this.user = user; + this.user = user != null ? user : LOGGED_OUT; + this.httpSession.setAttribute(EssayistSession.class.getName(), Boolean.valueOf(user != LOGGED_OUT)); } } diff --git a/src/main/java/com/moandjiezana/tent/essayist/MyFeedServlet.java b/src/main/java/com/moandjiezana/tent/essayist/MyFeedServlet.java index 21a927c..0181128 100644 --- a/src/main/java/com/moandjiezana/tent/essayist/MyFeedServlet.java +++ b/src/main/java/com/moandjiezana/tent/essayist/MyFeedServlet.java @@ -5,6 +5,7 @@ import com.moandjiezana.tent.client.TentClientAsync; import com.moandjiezana.tent.client.posts.Post; import com.moandjiezana.tent.client.posts.PostQuery; import com.moandjiezana.tent.client.users.Profile; +import com.moandjiezana.tent.essayist.auth.Authenticated; import com.moandjiezana.tent.essayist.tent.Entities; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.providers.jdk.JDKAsyncHttpProvider; @@ -50,6 +51,7 @@ public class MyFeedServlet extends HttpServlet { } @Override + @Authenticated protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { User user = sessions.get().getUser(); diff --git a/src/main/java/com/moandjiezana/tent/essayist/NewEssayServlet.java b/src/main/java/com/moandjiezana/tent/essayist/NewEssayServlet.java index 32dbc7f..919d79b 100644 --- a/src/main/java/com/moandjiezana/tent/essayist/NewEssayServlet.java +++ b/src/main/java/com/moandjiezana/tent/essayist/NewEssayServlet.java @@ -3,6 +3,7 @@ package com.moandjiezana.tent.essayist; import com.moandjiezana.tent.client.TentClient; import com.moandjiezana.tent.client.posts.Post; import com.moandjiezana.tent.client.users.Permissions; +import com.moandjiezana.tent.essayist.auth.Authenticated; import com.moandjiezana.tent.essayist.tent.Entities; import com.moandjiezana.tent.essayist.tent.EssayistPostContent; @@ -19,6 +20,7 @@ import javax.servlet.http.HttpServletResponse; import org.pegdown.PegDownProcessor; @Singleton +@Authenticated public class NewEssayServlet extends HttpServlet { private Templates templates; diff --git a/src/main/java/com/moandjiezana/tent/essayist/auth/Authenticated.java b/src/main/java/com/moandjiezana/tent/essayist/auth/Authenticated.java new file mode 100644 index 0000000..05c8c12 --- /dev/null +++ b/src/main/java/com/moandjiezana/tent/essayist/auth/Authenticated.java @@ -0,0 +1,14 @@ +package com.moandjiezana.tent.essayist.auth; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Retention(RUNTIME) +@Target({ METHOD, TYPE}) +public @interface Authenticated { + +} diff --git a/src/main/java/com/moandjiezana/tent/essayist/auth/AuthenticationInterceptor.java b/src/main/java/com/moandjiezana/tent/essayist/auth/AuthenticationInterceptor.java new file mode 100644 index 0000000..2223598 --- /dev/null +++ b/src/main/java/com/moandjiezana/tent/essayist/auth/AuthenticationInterceptor.java @@ -0,0 +1,62 @@ +package com.moandjiezana.tent.essayist.auth; + +import com.google.inject.matcher.Matcher; +import com.moandjiezana.tent.essayist.EssayistSession; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; + +public class AuthenticationInterceptor implements MethodInterceptor { + + @Override + public Object invoke(MethodInvocation invocation) throws Throwable { + HttpServletRequest request = (HttpServletRequest) invocation.getArguments()[0]; + HttpSession session = request.getSession(false); + if (session == null) { + + return refuse(invocation); + } + + Boolean sessionKey = (Boolean) request.getSession().getAttribute(EssayistSession.class.getName()); + if (sessionKey == null || Boolean.FALSE.equals(sessionKey)) { + return refuse(invocation); + } + + return invocation.proceed(); + } + + private Void refuse(MethodInvocation invocation) throws IOException { + HttpServletRequest request = (HttpServletRequest) invocation.getArguments()[0]; + HttpServletResponse response = (HttpServletResponse) invocation.getArguments()[1]; + response.sendRedirect(request.getContextPath()); + + return null; + } + + public static class MethodOfAuthenticatedClassMatcher implements Matcher { + + @Override + public boolean matches(Method method) { + return method.getName().startsWith("do") && method.getModifiers() == Modifier.PROTECTED; + } + + @Override + public Matcher and(Matcher other) { + throw new UnsupportedOperationException(); + } + + @Override + public Matcher or(Matcher other) { + throw new UnsupportedOperationException(); + } + + } +} diff --git a/src/main/java/com/moandjiezana/tent/essayist/config/EssayistServletContextListener.java b/src/main/java/com/moandjiezana/tent/essayist/config/EssayistServletContextListener.java index b6d7c7d..db88d31 100644 --- a/src/main/java/com/moandjiezana/tent/essayist/config/EssayistServletContextListener.java +++ b/src/main/java/com/moandjiezana/tent/essayist/config/EssayistServletContextListener.java @@ -5,6 +5,8 @@ import com.eroi.migrate.Engine; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; +import com.google.inject.matcher.Matcher; +import com.google.inject.matcher.Matchers; import com.google.inject.servlet.GuiceServletContextListener; import com.google.inject.servlet.ServletModule; import com.moandjiezana.tent.client.internal.com.google.common.base.Throwables; @@ -16,14 +18,18 @@ import com.moandjiezana.tent.essayist.LoginServlet; import com.moandjiezana.tent.essayist.LogoutServlet; import com.moandjiezana.tent.essayist.MyFeedServlet; import com.moandjiezana.tent.essayist.NewEssayServlet; +import com.moandjiezana.tent.essayist.auth.Authenticated; +import com.moandjiezana.tent.essayist.auth.AuthenticationInterceptor; import com.moandjiezana.tent.essayist.db.migrations.Migration_1; import java.io.IOException; +import java.lang.reflect.AnnotatedElement; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; import javax.servlet.ServletContextEvent; +import javax.servlet.http.HttpServlet; import org.apache.commons.dbutils.QueryRunner; import org.apache.tomcat.jdbc.pool.DataSource; @@ -99,6 +105,14 @@ public class EssayistServletContextListener extends GuiceServletContextListener @Override protected void configure() { bind(QueryRunner.class).toInstance(queryRunner); + + AuthenticationInterceptor authenticationInterceptor = new AuthenticationInterceptor(); + @SuppressWarnings("rawtypes") + Matcher servletSubclassMatcher = Matchers.subclassesOf(HttpServlet.class); + Matcher authenticationAnnotationMatcher = Matchers.annotatedWith(Authenticated.class); + + bindInterceptor(servletSubclassMatcher.and(authenticationAnnotationMatcher), new AuthenticationInterceptor.MethodOfAuthenticatedClassMatcher(), authenticationInterceptor); + bindInterceptor(servletSubclassMatcher, authenticationAnnotationMatcher, authenticationInterceptor); } }); }