| // Copyright (C) 2015 The Android Open Source Project | |
| // | |
| // Licensed 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 com.google.gerrit.httpd; | |
| import static com.google.common.base.Strings.emptyToNull; | |
| import static com.google.common.net.HttpHeaders.AUTHORIZATION; | |
| import static java.nio.charset.StandardCharsets.UTF_8; | |
| import com.google.common.io.BaseEncoding; | |
| import com.google.gerrit.common.Nullable; | |
| import javax.servlet.http.HttpServletRequest; | |
| public class RemoteUserUtil { | |
| /** | |
| * Tries to get username from a request with following strategies: | |
| * | |
| * <ul> | |
| * <li>ServletRequest#getRemoteUser | |
| * <li>HTTP 'Authorization' header | |
| * <li>Custom HTTP header | |
| * </ul> | |
| * | |
| * @param req request to extract username from. | |
| * @param loginHeader name of header which is used for extracting username. | |
| * @return the extracted username or null. | |
| */ | |
| public static String getRemoteUser(HttpServletRequest req, String loginHeader) { | |
| if (AUTHORIZATION.equals(loginHeader)) { | |
| String user = emptyToNull(req.getRemoteUser()); | |
| if (user != null) { | |
| // The container performed the authentication, and has the user | |
| // identity already decoded for us. Honor that as we have been | |
| // configured to honor HTTP authentication. | |
| return user; | |
| } | |
| // If the container didn't do the authentication we might | |
| // have done it in the front-end web server. Try to split | |
| // the identity out of the Authorization header and honor it. | |
| String auth = req.getHeader(AUTHORIZATION); | |
| return extractUsername(auth); | |
| } | |
| // Nonstandard HTTP header. We have been told to trust this | |
| // header blindly as-is. | |
| return emptyToNull(req.getHeader(loginHeader)); | |
| } | |
| /** | |
| * Extracts username from an HTTP Basic or Digest authentication header. | |
| * | |
| * @param auth header value which is used for extracting. | |
| * @return username if available or null. | |
| */ | |
| @Nullable | |
| public static String extractUsername(String auth) { | |
| auth = emptyToNull(auth); | |
| if (auth == null) { | |
| return null; | |
| } else if (auth.startsWith("Basic ")) { | |
| auth = auth.substring("Basic ".length()); | |
| auth = new String(BaseEncoding.base64().decode(auth), UTF_8); | |
| final int c = auth.indexOf(':'); | |
| return c > 0 ? auth.substring(0, c) : null; | |
| } else if (auth.startsWith("Digest ")) { | |
| final int u = auth.indexOf("username=\""); | |
| if (u <= 0) { | |
| return null; | |
| } | |
| auth = auth.substring(u + 10); | |
| final int e = auth.indexOf('"'); | |
| return e > 0 ? auth.substring(0, e) : null; | |
| } else { | |
| return null; | |
| } | |
| } | |
| } |