From 16052aeb4bad15bb41078a8440008d078bb074ab Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 26 Sep 2010 16:14:25 +0200 Subject: [PATCH] added BasicAuthenticationFilter --- .../web/filter/BasicAuthenticationFilter.java | 149 ++++++++++++++++++ .../SecurityHttpServletRequestWrapper.java | 83 ++++++++++ .../java/sonia/scm/filter/SecurityFilter.java | 77 +-------- 3 files changed, 237 insertions(+), 72 deletions(-) create mode 100644 scm-web-api/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java create mode 100644 scm-web-api/src/main/java/sonia/scm/web/filter/SecurityHttpServletRequestWrapper.java diff --git a/scm-web-api/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java b/scm-web-api/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java new file mode 100644 index 0000000000..ff29c1dc0d --- /dev/null +++ b/scm-web-api/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java @@ -0,0 +1,149 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + + + +package sonia.scm.web.filter; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.inject.Inject; +import com.google.inject.Singleton; + +import sonia.scm.User; +import sonia.scm.util.Util; +import sonia.scm.web.security.Authenticator; + +//~--- JDK imports ------------------------------------------------------------ + +import com.sun.jersey.core.util.Base64; + +import java.io.IOException; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * + * @author Sebastian Sdorra + */ +@Singleton +public class BasicAuthenticationFilter extends HttpFilter +{ + + /** Field description */ + public static final String AUTHENTICATION_REALM = "SONIA :: SCM Manager"; + + /** Field description */ + public static final String AUTHORIZATION_BASIC_PREFIX = "BASIC"; + + /** Field description */ + public static final String CREDENTIAL_SEPARATOR = ":"; + + /** Field description */ + public static final String HEADERVALUE_CONNECTION_CLOSE = "close"; + + /** Field description */ + public static final String HEADER_AUTHORIZATION = "Authorization"; + + /** Field description */ + public static final String HEADER_CONNECTION = "connection"; + + /** Field description */ + public static final String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate"; + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + * + * @param authenticator + */ + @Inject + public BasicAuthenticationFilter(Authenticator authenticator) + { + this.authenticator = authenticator; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param request + * @param response + * @param chain + * + * @throws IOException + * @throws ServletException + */ + @Override + protected void doFilter(HttpServletRequest request, + HttpServletResponse response, FilterChain chain) + throws IOException, ServletException + { + User user = authenticator.getUser(request); + + if (user == null) + { + String authentication = request.getHeader(HEADER_AUTHORIZATION); + + if (Util.isEmpty(authentication)) + { + sendUnauthorized(response); + } + else + { + if (!authentication.toUpperCase().startsWith( + AUTHORIZATION_BASIC_PREFIX)) + { + throw new ServletException("wrong basic header"); + } + + String token = authentication.substring(6); + + token = new String(Base64.decode(token.getBytes())); + + String[] credentials = token.split(CREDENTIAL_SEPARATOR); + + user = authenticator.authenticate(request, credentials[0], + credentials[1]); + } + } + + if (user != null) + { + chain.doFilter(new SecurityHttpServletRequestWrapper(request, user), + response); + } + else + { + sendUnauthorized(response); + } + } + + /** + * Method description + * + * + * @param response + */ + private void sendUnauthorized(HttpServletResponse response) + { + response.setHeader(HEADER_WWW_AUTHENTICATE, + "Basic realm=\"" + AUTHENTICATION_REALM + "\""); + response.setHeader(HEADER_CONNECTION, HEADERVALUE_CONNECTION_CLOSE); + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private Authenticator authenticator; +} diff --git a/scm-web-api/src/main/java/sonia/scm/web/filter/SecurityHttpServletRequestWrapper.java b/scm-web-api/src/main/java/sonia/scm/web/filter/SecurityHttpServletRequestWrapper.java new file mode 100644 index 0000000000..bc31bbecf9 --- /dev/null +++ b/scm-web-api/src/main/java/sonia/scm/web/filter/SecurityHttpServletRequestWrapper.java @@ -0,0 +1,83 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + + + +package sonia.scm.web.filter; + +//~--- non-JDK imports -------------------------------------------------------- + +import sonia.scm.User; + +//~--- JDK imports ------------------------------------------------------------ + +import java.security.Principal; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; + +/** + * + * @author Sebastian Sdorra + */ +public class SecurityHttpServletRequestWrapper extends HttpServletRequestWrapper +{ + + /** + * Constructs ... + * + * + * @param request + * @param user + */ + public SecurityHttpServletRequestWrapper(HttpServletRequest request, + User user) + { + super(request); + this.user = user; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + @Override + public String getRemoteUser() + { + return user.getName(); + } + + /** + * Method description + * + * + * @return + */ + public User getUser() + { + return user; + } + + /** + * Method description + * + * + * @return + */ + @Override + public Principal getUserPrincipal() + { + return user; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private User user; +} diff --git a/scm-webapp/src/main/java/sonia/scm/filter/SecurityFilter.java b/scm-webapp/src/main/java/sonia/scm/filter/SecurityFilter.java index 923cab900e..c23bbf81b0 100644 --- a/scm-webapp/src/main/java/sonia/scm/filter/SecurityFilter.java +++ b/scm-webapp/src/main/java/sonia/scm/filter/SecurityFilter.java @@ -9,11 +9,13 @@ package sonia.scm.filter; //~--- non-JDK imports -------------------------------------------------------- -import sonia.scm.web.filter.HttpFilter; import com.google.inject.Inject; import com.google.inject.Singleton; import sonia.scm.User; +import sonia.scm.web.filter.HttpFilter; +import sonia.scm.web.filter.SecurityHttpServletRequestWrapper; +import sonia.scm.web.security.Authenticator; //~--- JDK imports ------------------------------------------------------------ @@ -26,7 +28,6 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; -import sonia.scm.web.security.Authenticator; /** * @@ -66,7 +67,8 @@ public class SecurityFilter extends HttpFilter if (user != null) { - chain.doFilter(new ScmHttpServletRequest(request, user), response); + chain.doFilter(new SecurityHttpServletRequestWrapper(request, user), + response); } else { @@ -79,75 +81,6 @@ public class SecurityFilter extends HttpFilter } } - //~--- inner classes -------------------------------------------------------- - - /** - * Class description - * - * - * @version Enter version here..., 10/09/08 - * @author Enter your name here... - */ - private static class ScmHttpServletRequest extends HttpServletRequestWrapper - { - - /** - * Constructs ... - * - * - * @param request - * @param user - */ - public ScmHttpServletRequest(HttpServletRequest request, User user) - { - super(request); - this.user = user; - } - - //~--- get methods -------------------------------------------------------- - - /** - * Method description - * - * - * @return - */ - @Override - public String getRemoteUser() - { - return user.getName(); - } - - /** - * Method description - * - * - * @return - */ - public User getUser() - { - return user; - } - - /** - * Method description - * - * - * @return - */ - @Override - public Principal getUserPrincipal() - { - return user; - } - - //~--- fields ------------------------------------------------------------- - - /** Field description */ - private User user; - } - - //~--- fields --------------------------------------------------------------- /** Field description */