001/* 002 * Licensed to DuraSpace under one or more contributor license agreements. 003 * See the NOTICE file distributed with this work for additional information 004 * regarding copyright ownership. 005 * 006 * DuraSpace licenses this file to you under the Apache License, 007 * Version 2.0 (the "License"); you may not use this file except in 008 * compliance with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.fcrepo.http.commons.test.util; 019 020import static java.lang.reflect.Proxy.newProxyInstance; 021import static java.util.Collections.emptySet; 022import static java.util.Collections.singleton; 023import static javax.ws.rs.core.HttpHeaders.AUTHORIZATION; 024import static org.slf4j.LoggerFactory.getLogger; 025 026import java.io.IOException; 027import java.lang.reflect.InvocationHandler; 028import java.lang.reflect.Method; 029import java.security.Principal; 030import java.util.Set; 031 032import javax.servlet.Filter; 033import javax.servlet.FilterChain; 034import javax.servlet.FilterConfig; 035import javax.servlet.ServletException; 036import javax.servlet.ServletRequest; 037import javax.servlet.ServletResponse; 038import javax.servlet.http.HttpServletRequest; 039import javax.ws.rs.WebApplicationException; 040 041import org.glassfish.grizzly.http.server.GrizzlyPrincipal; 042import org.glassfish.jersey.internal.util.Base64; 043import org.slf4j.Logger; 044 045/** 046 * @author Gregory Jansen 047 */ 048public class TestAuthenticationRequestFilter implements Filter { 049 050 private static final Logger log = getLogger(TestAuthenticationRequestFilter.class); 051 052 private static final String FEDORA_ADMIN_USER = "fedoraAdmin"; 053 054 /* 055 * (non-Javadoc) 056 * @see 057 * com.sun.jersey.spi.container.ContainerRequestFilter#filter(com.sun.jersey 058 * .spi.container.ContainerRequest) 059 */ 060 @Override 061 public void doFilter(final ServletRequest request, 062 final ServletResponse response, final FilterChain chain) 063 throws IOException, ServletException { 064 final HttpServletRequest req = (HttpServletRequest) request; 065 final String username = getUsername(req); 066 // Validate the extracted credentials 067 Set<String> containerRoles = emptySet(); 068 if (username == null) { 069 log.debug("ANONYMOUS"); 070 } else if (FEDORA_ADMIN_USER.equals(username)) { 071 containerRoles = singleton("fedoraAdmin"); 072 log.debug("ADMIN AUTHENTICATED"); 073 } else if ("noroles".equals(username)) { 074 log.debug("USER (without roles); AUTHENTICATED"); 075 } else { 076 containerRoles = singleton("fedoraUser"); 077 log.debug("USER AUTHENTICATED"); 078 } 079 final ServletRequest proxy = proxy(req, username, containerRoles); 080 chain.doFilter(proxy, response); 081 } 082 083 private static ServletRequest proxy(final HttpServletRequest request, 084 final String username, final Set<String> containerRoles) { 085 final Principal user = username != null ? new GrizzlyPrincipal(username) : null; 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}