001/** 002 * Copyright 2015 DuraSpace, Inc. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.fcrepo.http.commons.test.util; 017 018import static java.lang.reflect.Proxy.newProxyInstance; 019import static java.util.Collections.emptySet; 020import static java.util.Collections.singleton; 021import static javax.ws.rs.core.HttpHeaders.AUTHORIZATION; 022import static org.slf4j.LoggerFactory.getLogger; 023 024import java.io.IOException; 025import java.lang.reflect.InvocationHandler; 026import java.lang.reflect.Method; 027import java.security.Principal; 028import java.util.Set; 029 030import javax.servlet.Filter; 031import javax.servlet.FilterChain; 032import javax.servlet.FilterConfig; 033import javax.servlet.ServletException; 034import javax.servlet.ServletRequest; 035import javax.servlet.ServletResponse; 036import javax.servlet.http.HttpServletRequest; 037import javax.ws.rs.WebApplicationException; 038 039import org.glassfish.grizzly.http.server.GrizzlyPrincipal; 040import org.glassfish.jersey.internal.util.Base64; 041import org.slf4j.Logger; 042 043/** 044 * @author Gregory Jansen 045 */ 046public class TestAuthenticationRequestFilter implements Filter { 047 048 private static final Logger log = getLogger(TestAuthenticationRequestFilter.class); 049 050 private static final String FEDORA_ADMIN_USER = "fedoraAdmin"; 051 052 /* 053 * (non-Javadoc) 054 * @see 055 * com.sun.jersey.spi.container.ContainerRequestFilter#filter(com.sun.jersey 056 * .spi.container.ContainerRequest) 057 */ 058 @Override 059 public void doFilter(final ServletRequest request, 060 final ServletResponse response, final FilterChain chain) 061 throws IOException, ServletException { 062 final HttpServletRequest req = (HttpServletRequest) request; 063 final String username = getUsername(req); 064 // Validate the extracted credentials 065 Set<String> containerRoles = emptySet(); 066 if (FEDORA_ADMIN_USER.equals(username)) { 067 containerRoles = singleton("fedoraAdmin"); 068 log.debug("ADMIN AUTHENTICATED"); 069 } else { 070 containerRoles = singleton("fedoraUser"); 071 log.debug("USER AUTHENTICATED"); 072 } 073 final ServletRequest proxy = proxy(req, username, containerRoles); 074 chain.doFilter(proxy, response); 075 } 076 077 /** 078 * @param request 079 * @param username 080 * @param containerRoles 081 * @return 082 */ 083 private static ServletRequest proxy(final HttpServletRequest request, 084 final String username, final Set<String> containerRoles) { 085 final Principal user = new GrizzlyPrincipal(username); 086 final HttpServletRequest result = 087 (HttpServletRequest) newProxyInstance(request.getClass() 088 .getClassLoader(), 089 new Class[] {HttpServletRequest.class}, 090 new InvocationHandler() { 091 092 @Override 093 public Object invoke(final Object proxy, 094 final Method method, final Object[] args) 095 throws Throwable { 096 if (method.getName().equals("isUserInRole")) { 097 final String role = (String) args[0]; 098 return containerRoles.contains(role); 099 } else if (method.getName().equals( 100 "getUserPrincipal")) { 101 return user; 102 } else if (method.getName().equals( 103 "getRemoteUser")) { 104 return username; 105 } 106 return method.invoke(request, args); 107 } 108 }); 109 return result; 110 } 111 112 private static String getUsername(final HttpServletRequest request) { 113 // Extract authentication credentials 114 String authentication = request.getHeader(AUTHORIZATION); 115 if (authentication == null) { 116 return null; 117 } 118 if (!authentication.startsWith("Basic ")) { 119 return null; 120 } 121 authentication = authentication.substring("Basic ".length()); 122 final String[] values = Base64.decodeAsString(authentication).split(":"); 123 if (values.length < 2) { 124 throw new WebApplicationException(400); 125 // "Invalid syntax for username and password" 126 } 127 final String username = values[0]; 128 final String password = values[1]; 129 if ((username == null) || (password == null)) { 130 return null; 131 } 132 return username; 133 } 134 135 /* 136 * (non-Javadoc) 137 * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) 138 */ 139 @Override 140 public void init(final FilterConfig filterConfig) { 141 } 142 143 /* 144 * (non-Javadoc) 145 * @see javax.servlet.Filter#destroy() 146 */ 147 @Override 148 public void destroy() { 149 } 150}