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 (FEDORA_ADMIN_USER.equals(username)) { 069 containerRoles = singleton("fedoraAdmin"); 070 log.debug("ADMIN AUTHENTICATED"); 071 } else { 072 containerRoles = singleton("fedoraUser"); 073 log.debug("USER AUTHENTICATED"); 074 } 075 final ServletRequest proxy = proxy(req, username, containerRoles); 076 chain.doFilter(proxy, response); 077 } 078 079 /** 080 * @param request 081 * @param username 082 * @param containerRoles 083 * @return 084 */ 085 private static ServletRequest proxy(final HttpServletRequest request, 086 final String username, final Set<String> containerRoles) { 087 final Principal user = new GrizzlyPrincipal(username); 088 final HttpServletRequest result = 089 (HttpServletRequest) newProxyInstance(request.getClass() 090 .getClassLoader(), 091 new Class[] {HttpServletRequest.class}, 092 new InvocationHandler() { 093 094 @Override 095 public Object invoke(final Object proxy, 096 final Method method, final Object[] args) 097 throws Throwable { 098 if (method.getName().equals("isUserInRole")) { 099 final String role = (String) args[0]; 100 return containerRoles.contains(role); 101 } else if (method.getName().equals( 102 "getUserPrincipal")) { 103 return user; 104 } else if (method.getName().equals( 105 "getRemoteUser")) { 106 return username; 107 } 108 return method.invoke(request, args); 109 } 110 }); 111 return result; 112 } 113 114 private static String getUsername(final HttpServletRequest request) { 115 // Extract authentication credentials 116 String authentication = request.getHeader(AUTHORIZATION); 117 if (authentication == null) { 118 return null; 119 } 120 if (!authentication.startsWith("Basic ")) { 121 return null; 122 } 123 authentication = authentication.substring("Basic ".length()); 124 final String[] values = Base64.decodeAsString(authentication).split(":"); 125 if (values.length < 2) { 126 throw new WebApplicationException(400); 127 // "Invalid syntax for username and password" 128 } 129 final String username = values[0]; 130 final String password = values[1]; 131 if ((username == null) || (password == null)) { 132 return null; 133 } 134 return username; 135 } 136 137 /* 138 * (non-Javadoc) 139 * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) 140 */ 141 @Override 142 public void init(final FilterConfig filterConfig) { 143 } 144 145 /* 146 * (non-Javadoc) 147 * @see javax.servlet.Filter#destroy() 148 */ 149 @Override 150 public void destroy() { 151 } 152}