3 * Copyright (C) 2009-2023 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.server.authentication;
22 import com.google.common.collect.ImmutableSet;
23 import java.io.IOException;
25 import javax.servlet.FilterChain;
26 import javax.servlet.FilterConfig;
27 import javax.servlet.ServletException;
28 import javax.servlet.ServletRequest;
29 import javax.servlet.ServletResponse;
30 import javax.servlet.http.HttpServletRequest;
31 import javax.servlet.http.HttpServletResponse;
32 import org.sonar.api.config.Configuration;
33 import org.sonar.api.web.ServletFilter;
34 import org.sonar.server.user.ThreadLocalUserSession;
36 import static org.sonar.api.web.ServletFilter.UrlPattern.Builder.staticResourcePatterns;
37 import static org.sonar.server.authentication.AuthenticationRedirection.redirectTo;
39 public class DefaultAdminCredentialsVerifierFilter extends ServletFilter {
40 private static final String RESET_PASSWORD_PATH = "/account/reset_password";
41 private static final String CHANGE_ADMIN_PASSWORD_PATH = "/admin/change_admin_password";
42 // This property is used by Orchestrator to disable this force redirect. It should never be used in production, which
43 // is why this is not defined in org.sonar.process.ProcessProperties.
44 private static final String SONAR_FORCE_REDIRECT_DEFAULT_ADMIN_CREDENTIALS = "sonar.forceRedirectOnDefaultAdminCredentials";
46 private static final Set<String> SKIPPED_URLS = ImmutableSet.of(
48 CHANGE_ADMIN_PASSWORD_PATH,
49 "/batch/*", "/api/*");
51 private final Configuration config;
52 private final DefaultAdminCredentialsVerifier defaultAdminCredentialsVerifier;
53 private final ThreadLocalUserSession userSession;
55 public DefaultAdminCredentialsVerifierFilter(Configuration config, DefaultAdminCredentialsVerifier defaultAdminCredentialsVerifier, ThreadLocalUserSession userSession) {
57 this.defaultAdminCredentialsVerifier = defaultAdminCredentialsVerifier;
58 this.userSession = userSession;
62 public UrlPattern doGetPattern() {
63 return UrlPattern.builder()
65 .excludes(staticResourcePatterns())
66 .excludes(SKIPPED_URLS)
71 public void init(FilterConfig filterConfig) {
76 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
77 HttpServletRequest request = (HttpServletRequest) servletRequest;
78 HttpServletResponse response = (HttpServletResponse) servletResponse;
79 boolean forceRedirect = config
80 .getBoolean(SONAR_FORCE_REDIRECT_DEFAULT_ADMIN_CREDENTIALS)
83 if (forceRedirect && userSession.hasSession() && userSession.isLoggedIn()
84 && userSession.isSystemAdministrator() && !"admin".equals(userSession.getLogin())
85 && defaultAdminCredentialsVerifier.hasDefaultCredentialUser()) {
86 redirectTo(response, request.getContextPath() + CHANGE_ADMIN_PASSWORD_PATH);
89 chain.doFilter(request, response);
93 public void destroy() {