| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.ambari.server.api; |
| |
| import java.io.IOException; |
| import java.net.URLDecoder; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| import javax.servlet.Filter; |
| import javax.servlet.FilterChain; |
| import javax.servlet.FilterConfig; |
| import javax.servlet.ServletException; |
| import javax.servlet.ServletRequest; |
| import javax.servlet.ServletResponse; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletRequestWrapper; |
| |
| import org.apache.ambari.server.security.authorization.AuthorizationHelper; |
| |
| /** |
| * This filter overrides usernames found in request url. |
| */ |
| public class UserNameOverrideFilter implements Filter { |
| |
| // Regex for extracting user name component from the user related api request Uris |
| private final static Pattern USER_NAME_IN_URI_REGEXP = Pattern.compile("(?<pre>.*/users/)(?<username>[^/]+)(?<post>(/.*)?)"); |
| |
| /** |
| * Called by the web container to indicate to a filter that it is |
| * being placed into service. |
| * |
| * <p>The servlet container calls the init |
| * method exactly once after instantiating the filter. The init |
| * method must complete successfully before the filter is asked to do any |
| * filtering work. |
| * |
| * <p>The web container cannot place the filter into service if the init |
| * method either |
| * <ol> |
| * <li>Throws a ServletException |
| * <li>Does not return within a time period defined by the web container |
| * </ol> |
| * |
| * @param filterConfig |
| */ |
| @Override |
| public void init(FilterConfig filterConfig) throws ServletException { |
| |
| } |
| |
| /** |
| * The <code>doFilter</code> method of the Filter is called by the |
| * container each time a request/response pair is passed through the |
| * chain due to a client request for a resource at the end of the chain. |
| * The FilterChain passed in to this method allows the Filter to pass |
| * on the request and response to the next entity in the chain. |
| * |
| * Verify if this a user related request by checking that the Uri of the request contains |
| * username and resolves the username to actual ambari user name if username |
| * is a login alias. |
| * |
| * @param request |
| * @param response |
| * @param chain |
| */ |
| @Override |
| public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { |
| if (request instanceof HttpServletRequest) { |
| final HttpServletRequest httpServletRequest = (HttpServletRequest) request; |
| Matcher userNameMatcher = getUserNameMatcher(httpServletRequest.getRequestURI()); |
| |
| if (userNameMatcher.find()) { |
| String userNameFromUri = URLDecoder.decode(userNameMatcher.group("username"), "UTF-8"); |
| final String userName = AuthorizationHelper.resolveLoginAliasToUserName(userNameFromUri); |
| |
| if (!userNameFromUri.equals(userName)) { |
| final String requestUriOverride = String.format("%s%s%s", userNameMatcher.group("pre"), userName, userNameMatcher.group("post")); |
| |
| request = new HttpServletRequestWrapper(httpServletRequest) { |
| @Override |
| public String getRequestURI() { |
| return requestUriOverride; |
| } |
| }; |
| |
| } |
| } |
| } |
| |
| chain.doFilter(request, response); |
| } |
| |
| /** |
| * Returns a {@link Matcher} created from {@link #USER_NAME_IN_URI_REGEXP} for the |
| * provided requestUri. |
| * @param requestUri the Uri the Matcher is created for. |
| * @return the matcher |
| */ |
| protected Matcher getUserNameMatcher(String requestUri) { |
| return USER_NAME_IN_URI_REGEXP.matcher(requestUri); |
| } |
| |
| /** |
| * Called by the web container to indicate to a filter that it is being |
| * taken out of service. |
| * |
| * <p>This method is only called once all threads within the filter's |
| * doFilter method have exited or after a timeout period has passed. |
| * After the web container calls this method, it will not call the |
| * doFilter method again on this instance of the filter. |
| * |
| * <p>This method gives the filter an opportunity to clean up any |
| * resources that are being held (for example, memory, file handles, |
| * threads) and make sure that any persistent state is synchronized |
| * with the filter's current state in memory. |
| */ |
| @Override |
| public void destroy() { |
| |
| } |
| } |