001/* 002 * The contents of this file are subject to the license and copyright 003 * detailed in the LICENSE and NOTICE files at the root of the source 004 * tree. 005 */ 006package org.fcrepo.http.commons.test.util; 007 008import static java.lang.reflect.Proxy.newProxyInstance; 009import static java.util.Collections.emptySet; 010import static java.util.Collections.singleton; 011import static javax.ws.rs.core.HttpHeaders.AUTHORIZATION; 012import static org.slf4j.LoggerFactory.getLogger; 013 014import java.io.IOException; 015import java.lang.reflect.InvocationHandler; 016import java.lang.reflect.Method; 017import java.security.Principal; 018import java.util.Base64; 019import java.util.Set; 020 021import javax.servlet.Filter; 022import javax.servlet.FilterChain; 023import javax.servlet.FilterConfig; 024import javax.servlet.ServletException; 025import javax.servlet.ServletRequest; 026import javax.servlet.ServletResponse; 027import javax.servlet.http.HttpServletRequest; 028import javax.ws.rs.WebApplicationException; 029 030import org.glassfish.grizzly.http.server.GrizzlyPrincipal; 031import org.slf4j.Logger; 032 033/** 034 * @author Gregory Jansen 035 */ 036public class TestAuthenticationRequestFilter implements Filter { 037 038 private static final Logger log = getLogger(TestAuthenticationRequestFilter.class); 039 040 private static final String FEDORA_ADMIN_USER = "fedoraAdmin"; 041 042 /* 043 * (non-Javadoc) 044 * @see 045 * com.sun.jersey.spi.container.ContainerRequestFilter#filter(com.sun.jersey 046 * .spi.container.ContainerRequest) 047 */ 048 @Override 049 public void doFilter(final ServletRequest request, 050 final ServletResponse response, final FilterChain chain) 051 throws IOException, ServletException { 052 final HttpServletRequest req = (HttpServletRequest) request; 053 final String username = getUsername(req); 054 // Validate the extracted credentials 055 Set<String> containerRoles = emptySet(); 056 if (username == null) { 057 log.debug("ANONYMOUS"); 058 } else if (FEDORA_ADMIN_USER.equals(username)) { 059 containerRoles = singleton("fedoraAdmin"); 060 log.debug("ADMIN AUTHENTICATED"); 061 } else if ("noroles".equals(username)) { 062 log.debug("USER (without roles); AUTHENTICATED"); 063 } else { 064 containerRoles = singleton("fedoraUser"); 065 log.debug("USER AUTHENTICATED"); 066 } 067 final ServletRequest proxy = proxy(req, username, containerRoles); 068 chain.doFilter(proxy, response); 069 } 070 071 private static ServletRequest proxy(final HttpServletRequest request, 072 final String username, final Set<String> containerRoles) { 073 final Principal user = username != null ? new GrizzlyPrincipal(username) : null; 074 final HttpServletRequest result = 075 (HttpServletRequest) newProxyInstance(request.getClass() 076 .getClassLoader(), 077 new Class[] {HttpServletRequest.class}, 078 new InvocationHandler() { 079 080 @Override 081 public Object invoke(final Object proxy, 082 final Method method, final Object[] args) 083 throws Throwable { 084 if (method.getName().equals("isUserInRole")) { 085 final String role = (String) args[0]; 086 return containerRoles.contains(role); 087 } else if (method.getName().equals( 088 "getUserPrincipal")) { 089 return user; 090 } else if (method.getName().equals( 091 "getRemoteUser")) { 092 return username; 093 } 094 return method.invoke(request, args); 095 } 096 }); 097 return result; 098 } 099 100 private static String getUsername(final HttpServletRequest request) { 101 // Extract authentication credentials 102 String authentication = request.getHeader(AUTHORIZATION); 103 if (authentication == null) { 104 return null; 105 } 106 if (!authentication.startsWith("Basic ")) { 107 return null; 108 } 109 authentication = authentication.substring("Basic ".length()); 110 final String[] values = new String(Base64.getDecoder().decode(authentication)).split(":"); 111 if (values.length < 2) { 112 throw new WebApplicationException(400); 113 // "Invalid syntax for username and password" 114 } 115 final String username = values[0]; 116 final String password = values[1]; 117 if ((username == null) || (password == null)) { 118 return null; 119 } 120 return username; 121 } 122 123 /* 124 * (non-Javadoc) 125 * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) 126 */ 127 @Override 128 public void init(final FilterConfig filterConfig) { 129 } 130 131 /* 132 * (non-Javadoc) 133 * @see javax.servlet.Filter#destroy() 134 */ 135 @Override 136 public void destroy() { 137 } 138}