diff options
author | Antoine Vinot <antoine.vinot@sonarsource.com> | 2023-04-13 16:57:56 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2023-04-24 20:04:23 +0000 |
commit | 68977b2bedc95c738b58bc8be83a00d21e13c32e (patch) | |
tree | 3c77243a1b04651f6cb7031e825901e40a37df79 /server/sonar-webserver-webapi | |
parent | f6aef43f6848a27861171cc8e757085326a334f2 (diff) | |
download | sonarqube-68977b2bedc95c738b58bc8be83a00d21e13c32e.tar.gz sonarqube-68977b2bedc95c738b58bc8be83a00d21e13c32e.zip |
SONAR-19045 Migrate from javaxi.servlet to framework agnostic plugin api classes
Co-authored-by: Eric Giffon <eric.giffon@sonarsource.com>
Co-authored-by: Alain Kermis <alain.kermis@sonarsource.com>
Co-authored-by: Antoine Vinot <antoine.vinot@sonarsource.com>
Co-authored-by: Jacek Poreda <jacek.poreda@sonarsource.com>
Diffstat (limited to 'server/sonar-webserver-webapi')
12 files changed, 156 insertions, 184 deletions
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/authentication/ws/LoginActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/authentication/ws/LoginActionIT.java index 364c0b4f25a..e9f7ce8169d 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/authentication/ws/LoginActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/authentication/ws/LoginActionIT.java @@ -19,14 +19,14 @@ */ package org.sonar.server.authentication.ws; -import javax.servlet.FilterChain; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.sonar.api.server.http.HttpRequest; +import org.sonar.api.server.http.HttpResponse; import org.sonar.api.server.ws.WebService; import org.sonar.api.utils.System2; +import org.sonar.api.web.FilterChain; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; @@ -60,23 +60,23 @@ public class LoginActionIT { @Rule public DbTester dbTester = DbTester.create(System2.INSTANCE); - private DbClient dbClient = dbTester.getDbClient(); + private final DbClient dbClient = dbTester.getDbClient(); - private DbSession dbSession = dbTester.getSession(); + private final DbSession dbSession = dbTester.getSession(); - private ThreadLocalUserSession threadLocalUserSession = new ThreadLocalUserSession(); + private final ThreadLocalUserSession threadLocalUserSession = new ThreadLocalUserSession(); - private HttpServletRequest request = mock(HttpServletRequest.class); - private HttpServletResponse response = mock(HttpServletResponse.class); - private FilterChain chain = mock(FilterChain.class); + private final HttpRequest request = mock(HttpRequest.class); + private final HttpResponse response = mock(HttpResponse.class); + private final FilterChain chain = mock(FilterChain.class); - private CredentialsAuthentication credentialsAuthentication = mock(CredentialsAuthentication.class); - private JwtHttpHandler jwtHttpHandler = mock(JwtHttpHandler.class); - private AuthenticationEvent authenticationEvent = mock(AuthenticationEvent.class); - private TestUserSessionFactory userSessionFactory = TestUserSessionFactory.standalone(); + private final CredentialsAuthentication credentialsAuthentication = mock(CredentialsAuthentication.class); + private final JwtHttpHandler jwtHttpHandler = mock(JwtHttpHandler.class); + private final AuthenticationEvent authenticationEvent = mock(AuthenticationEvent.class); + private final TestUserSessionFactory userSessionFactory = TestUserSessionFactory.standalone(); - private UserDto user = UserTesting.newUserDto().setLogin(LOGIN); - private LoginAction underTest = new LoginAction(credentialsAuthentication, jwtHttpHandler, threadLocalUserSession, authenticationEvent, userSessionFactory); + private final UserDto user = UserTesting.newUserDto().setLogin(LOGIN); + private final LoginAction underTest = new LoginAction(credentialsAuthentication, jwtHttpHandler, threadLocalUserSession, authenticationEvent, userSessionFactory); @Before public void setUp() { @@ -131,7 +131,7 @@ public class LoginActionIT { } @Test - public void return_authorized_code_when_unauthorized_exception_is_thrown() throws Exception { + public void return_authorized_code_when_unauthorized_exception_is_thrown() { doThrow(new UnauthorizedException("error !")).when(credentialsAuthentication).authenticate(new Credentials(LOGIN, PASSWORD), request, FORM); executeRequest(LOGIN, PASSWORD); @@ -142,28 +142,28 @@ public class LoginActionIT { } @Test - public void return_unauthorized_code_when_no_login() throws Exception { + public void return_unauthorized_code_when_no_login() { executeRequest(null, PASSWORD); verify(response).setStatus(401); verify(authenticationEvent).loginFailure(eq(request), any(AuthenticationException.class)); } @Test - public void return_unauthorized_code_when_empty_login() throws Exception { + public void return_unauthorized_code_when_empty_login() { executeRequest("", PASSWORD); verify(response).setStatus(401); verify(authenticationEvent).loginFailure(eq(request), any(AuthenticationException.class)); } @Test - public void return_unauthorized_code_when_no_password() throws Exception { + public void return_unauthorized_code_when_no_password() { executeRequest(LOGIN, null); verify(response).setStatus(401); verify(authenticationEvent).loginFailure(eq(request), any(AuthenticationException.class)); } @Test - public void return_unauthorized_code_when_empty_password() throws Exception { + public void return_unauthorized_code_when_empty_password() { executeRequest(LOGIN, ""); verify(response).setStatus(401); verify(authenticationEvent).loginFailure(eq(request), any(AuthenticationException.class)); diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/ChangePasswordActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/ChangePasswordActionIT.java index a1fdd23020d..83b30b34dba 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/ChangePasswordActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/ChangePasswordActionIT.java @@ -22,17 +22,17 @@ package org.sonar.server.user.ws; import java.io.IOException; import java.util.Optional; import javax.annotation.Nullable; -import javax.servlet.FilterChain; import javax.servlet.ServletOutputStream; import javax.servlet.WriteListener; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.sonar.api.config.internal.MapSettings; +import org.sonar.api.server.http.HttpRequest; +import org.sonar.api.server.http.HttpResponse; import org.sonar.api.server.ws.WebService; +import org.sonar.api.web.FilterChain; import org.sonar.db.DbSession; import org.sonar.db.DbTester; import org.sonar.db.audit.NoOpAuditPersister; @@ -75,8 +75,8 @@ public class ChangePasswordActionIT { private final ArgumentCaptor<UserDto> userDtoCaptor = ArgumentCaptor.forClass(UserDto.class); - private final HttpServletRequest request = mock(HttpServletRequest.class); - private final HttpServletResponse response = mock(HttpServletResponse.class); + private final HttpRequest request = mock(HttpRequest.class); + private final HttpResponse response = mock(HttpResponse.class); private final FilterChain chain = mock(FilterChain.class); private final MapSettings settings = new MapSettings().setProperty("sonar.internal.pbkdf2.iterations", "1"); @@ -88,7 +88,7 @@ public class ChangePasswordActionIT { private final JwtHttpHandler jwtHttpHandler = mock(JwtHttpHandler.class); - private final ChangePasswordAction changePasswordAction = new ChangePasswordAction(db.getDbClient(), userUpdater, userSessionRule, localAuthentication, jwtHttpHandler); + private final ChangePasswordAction underTest = new ChangePasswordAction(db.getDbClient(), userUpdater, userSessionRule, localAuthentication, jwtHttpHandler); private ServletOutputStream responseOutputStream; @Before @@ -147,7 +147,8 @@ public class ChangePasswordActionIT { userSessionRule.logIn(user.getLogin()); UserTestData anotherLocalUser = createLocalUser(); - assertThatThrownBy(() -> executeTest(anotherLocalUser.getLogin(), "I dunno", NEW_PASSWORD)) + String anotherLocalUserLogin = anotherLocalUser.getLogin(); + assertThatThrownBy(() -> executeTest(anotherLocalUserLogin, "I dunno", NEW_PASSWORD)) .isInstanceOf(ForbiddenException.class); verifyNoInteractions(jwtHttpHandler); assertThat(findSessionTokenDto(db.getSession(), user.getSessionTokenUuid())).isPresent(); @@ -184,9 +185,10 @@ public class ChangePasswordActionIT { UserDto user = db.users().insertUser(u -> u.setActive(false)); userSessionRule.logIn(user); - assertThatThrownBy(() -> executeTest(user.getLogin(), null, "polop")) + String userLogin = user.getLogin(); + assertThatThrownBy(() -> executeTest(userLogin, null, "polop")) .isInstanceOf(NotFoundException.class) - .hasMessage(format("User with login '%s' has not been found", user.getLogin())); + .hasMessage(format("User with login '%s' has not been found", userLogin)); verifyNoInteractions(jwtHttpHandler); } @@ -218,7 +220,6 @@ public class ChangePasswordActionIT { UserTestData user = createLocalUser(); userSessionRule.logIn(user.userDto()); - executeTest(user.getLogin(), OLD_PASSWORD, null); verify(response).setStatus(HTTP_BAD_REQUEST); assertThat(responseOutputStream).hasToString("{\"result\":\"The 'password' parameter is missing\"}"); @@ -267,7 +268,7 @@ public class ChangePasswordActionIT { WebService.Context context = new WebService.Context(); WebService.NewController newController = context.createController(controllerKey); - changePasswordAction.define(newController); + underTest.define(newController); newController.done(); WebService.Action changePassword = context.controller(controllerKey).action("change_password"); @@ -283,7 +284,7 @@ public class ChangePasswordActionIT { when(request.getParameter(PARAM_LOGIN)).thenReturn(login); when(request.getParameter(PARAM_PREVIOUS_PASSWORD)).thenReturn(oldPassword); when(request.getParameter(PARAM_PASSWORD)).thenReturn(newPassword); - changePasswordAction.doFilter(request, response, chain); + underTest.doFilter(request, response, chain); } private UserTestData createLocalUser(String password) { diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/authentication/ws/LoginAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/authentication/ws/LoginAction.java index 3c8eb7c21e6..a1c0b780f0e 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/authentication/ws/LoginAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/authentication/ws/LoginAction.java @@ -19,14 +19,12 @@ */ package org.sonar.server.authentication.ws; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import org.sonar.api.server.http.HttpRequest; +import org.sonar.api.server.http.HttpResponse; import org.sonar.api.server.ws.WebService; -import org.sonar.api.web.ServletFilter; +import org.sonar.api.web.FilterChain; +import org.sonar.api.web.HttpFilter; +import org.sonar.api.web.UrlPattern; import org.sonar.db.user.UserDto; import org.sonar.server.authentication.Credentials; import org.sonar.server.authentication.CredentialsAuthentication; @@ -46,7 +44,7 @@ import static org.sonar.server.authentication.event.AuthenticationEvent.Source; import static org.sonar.server.authentication.ws.AuthenticationWs.AUTHENTICATION_CONTROLLER; import static org.sonarqube.ws.client.WsRequest.Method.POST; -public class LoginAction extends ServletFilter implements AuthenticationWsAction { +public class LoginAction extends HttpFilter implements AuthenticationWsAction { private static final String LOGIN_ACTION = "login"; public static final String LOGIN_URL = "/" + AUTHENTICATION_CONTROLLER + "/" + LOGIN_ACTION; @@ -87,10 +85,7 @@ public class LoginAction extends ServletFilter implements AuthenticationWsAction } @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) { - HttpServletRequest request = (HttpServletRequest) servletRequest; - HttpServletResponse response = (HttpServletResponse) servletResponse; - + public void doFilter(HttpRequest request, HttpResponse response, FilterChain chain) { if (!request.getMethod().equals(POST.name())) { response.setStatus(HTTP_BAD_REQUEST); return; @@ -108,7 +103,7 @@ public class LoginAction extends ServletFilter implements AuthenticationWsAction } } - private UserDto authenticate(HttpServletRequest request) { + private UserDto authenticate(HttpRequest request) { String login = request.getParameter("login"); String password = request.getParameter("password"); if (isEmpty(login) || isEmpty(password)) { @@ -122,7 +117,7 @@ public class LoginAction extends ServletFilter implements AuthenticationWsAction } @Override - public void init(FilterConfig filterConfig) { + public void init() { // Nothing to do } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/authentication/ws/LogoutAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/authentication/ws/LogoutAction.java index 32990dfa2b0..f655bfa3d7b 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/authentication/ws/LogoutAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/authentication/ws/LogoutAction.java @@ -20,14 +20,12 @@ package org.sonar.server.authentication.ws; import java.util.Optional; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import org.sonar.api.server.http.HttpRequest; +import org.sonar.api.server.http.HttpResponse; import org.sonar.api.server.ws.WebService; -import org.sonar.api.web.ServletFilter; +import org.sonar.api.web.FilterChain; +import org.sonar.api.web.HttpFilter; +import org.sonar.api.web.UrlPattern; import org.sonar.server.authentication.JwtHttpHandler; import org.sonar.server.authentication.event.AuthenticationEvent; import org.sonar.server.authentication.event.AuthenticationException; @@ -37,7 +35,7 @@ import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; import static org.sonar.server.authentication.ws.AuthenticationWs.AUTHENTICATION_CONTROLLER; import static org.sonarqube.ws.client.WsRequest.Method.POST; -public class LogoutAction extends ServletFilter implements AuthenticationWsAction { +public class LogoutAction extends HttpFilter implements AuthenticationWsAction { private static final String LOGOUT_ACTION = "logout"; public static final String LOGOUT_URL = "/" + AUTHENTICATION_CONTROLLER + "/" + LOGOUT_ACTION; @@ -65,10 +63,7 @@ public class LogoutAction extends ServletFilter implements AuthenticationWsActio } @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) { - HttpServletRequest request = (HttpServletRequest) servletRequest; - HttpServletResponse response = (HttpServletResponse) servletResponse; - + public void doFilter(HttpRequest request, HttpResponse response, FilterChain chain) { if (!request.getMethod().equals(POST.name())) { response.setStatus(HTTP_BAD_REQUEST); return; @@ -76,7 +71,7 @@ public class LogoutAction extends ServletFilter implements AuthenticationWsActio logout(request, response); } - private void logout(HttpServletRequest request, HttpServletResponse response) { + private void logout(HttpRequest request, HttpResponse response) { generateAuthenticationEvent(request, response); jwtHttpHandler.removeToken(request, response); } @@ -84,7 +79,7 @@ public class LogoutAction extends ServletFilter implements AuthenticationWsActio /** * The generation of the authentication event should not prevent the removal of JWT cookie, that's why it's done in a separate method */ - private void generateAuthenticationEvent(HttpServletRequest request, HttpServletResponse response) { + private void generateAuthenticationEvent(HttpRequest request, HttpResponse response) { try { Optional<JwtHttpHandler.Token> token = jwtHttpHandler.getToken(request, response); String userLogin = token.map(value -> value.getUserDto().getLogin()).orElse(null); @@ -95,7 +90,7 @@ public class LogoutAction extends ServletFilter implements AuthenticationWsActio } @Override - public void init(FilterConfig filterConfig) { + public void init() { // Nothing to do } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/authentication/ws/ValidateAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/authentication/ws/ValidateAction.java index 1bc34b12997..47648970620 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/authentication/ws/ValidateAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/authentication/ws/ValidateAction.java @@ -22,16 +22,14 @@ package org.sonar.server.authentication.ws; import com.google.common.io.Resources; import java.io.IOException; import java.util.Optional; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import org.sonar.api.config.Configuration; +import org.sonar.api.server.http.HttpRequest; +import org.sonar.api.server.http.HttpResponse; import org.sonar.api.server.ws.WebService; import org.sonar.api.utils.text.JsonWriter; -import org.sonar.api.web.ServletFilter; +import org.sonar.api.web.FilterChain; +import org.sonar.api.web.HttpFilter; +import org.sonar.api.web.UrlPattern; import org.sonar.db.user.UserDto; import org.sonar.server.authentication.BasicAuthentication; import org.sonar.server.authentication.JwtHttpHandler; @@ -43,7 +41,7 @@ import static org.sonar.api.CoreProperties.CORE_FORCE_AUTHENTICATION_DEFAULT_VAL import static org.sonar.api.CoreProperties.CORE_FORCE_AUTHENTICATION_PROPERTY; import static org.sonar.server.authentication.ws.AuthenticationWs.AUTHENTICATION_CONTROLLER; -public class ValidateAction extends ServletFilter implements AuthenticationWsAction { +public class ValidateAction extends HttpFilter implements AuthenticationWsAction { private static final String VALIDATE_ACTION = "validate"; public static final String VALIDATE_URL = "/" + AUTHENTICATION_CONTROLLER + "/" + VALIDATE_ACTION; @@ -73,10 +71,7 @@ public class ValidateAction extends ServletFilter implements AuthenticationWsAct } @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException { - HttpServletRequest request = (HttpServletRequest) servletRequest; - HttpServletResponse response = (HttpServletResponse) servletResponse; - + public void doFilter(HttpRequest request, HttpResponse response, FilterChain filterChain) throws IOException { boolean isAuthenticated = authenticate(request, response); response.setContentType(MediaTypes.JSON); @@ -87,7 +82,7 @@ public class ValidateAction extends ServletFilter implements AuthenticationWsAct } } - private boolean authenticate(HttpServletRequest request, HttpServletResponse response) { + private boolean authenticate(HttpRequest request, HttpResponse response) { try { Optional<UserDto> user = jwtHttpHandler.validateToken(request, response); if (user.isPresent()) { @@ -104,7 +99,7 @@ public class ValidateAction extends ServletFilter implements AuthenticationWsAct } @Override - public void init(FilterConfig filterConfig) { + public void init() { // Nothing to do } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/saml/ws/ValidationAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/saml/ws/ValidationAction.java index c55a99f37f7..8a2b5534180 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/saml/ws/ValidationAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/saml/ws/ValidationAction.java @@ -22,15 +22,14 @@ package org.sonar.server.saml.ws; import java.io.IOException; import java.util.Arrays; import java.util.stream.Collectors; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; -import javax.servlet.http.HttpServletResponse; +import org.sonar.api.server.http.HttpRequest; +import org.sonar.api.server.http.HttpResponse; import org.sonar.api.server.ws.WebService; -import org.sonar.api.web.ServletFilter; +import org.sonar.api.web.FilterChain; +import org.sonar.api.web.HttpFilter; +import org.sonar.api.web.UrlPattern; import org.sonar.auth.saml.SamlAuthenticator; import org.sonar.auth.saml.SamlIdentityProvider; import org.sonar.server.authentication.AuthenticationError; @@ -39,12 +38,13 @@ import org.sonar.server.authentication.OAuthCsrfVerifier; import org.sonar.server.authentication.SamlValidationCspHeaders; import org.sonar.server.authentication.SamlValidationRedirectionFilter; import org.sonar.server.authentication.event.AuthenticationException; +import org.sonar.server.http.JavaxHttpRequest; import org.sonar.server.user.ThreadLocalUserSession; import org.sonar.server.ws.ServletFilterHandler; import static org.sonar.server.saml.ws.SamlValidationWs.SAML_VALIDATION_CONTROLLER; -public class ValidationAction extends ServletFilter implements SamlAction { +public class ValidationAction extends HttpFilter implements SamlAction { static final String VALIDATION_CALLBACK_KEY = SamlValidationRedirectionFilter.SAML_VALIDATION_KEY; private static final String URL_DELIMITER = "/"; @@ -69,35 +69,32 @@ public class ValidationAction extends ServletFilter implements SamlAction { } @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - HttpServletResponse httpResponse = (HttpServletResponse) response; - HttpServletRequest httpRequest = (HttpServletRequest) request; - + public void doFilter(HttpRequest request, HttpResponse response, FilterChain filterChain) throws IOException { try { - oAuthCsrfVerifier.verifyState(httpRequest, httpResponse, samlIdentityProvider, "CSRFToken"); + oAuthCsrfVerifier.verifyState(request, response, samlIdentityProvider, "CSRFToken"); } catch (AuthenticationException exception) { - AuthenticationError.handleError(httpRequest, httpResponse, exception.getMessage()); + AuthenticationError.handleError(request, response, exception.getMessage()); return; } if (!userSession.hasSession() || !userSession.isSystemAdministrator()) { - AuthenticationError.handleError(httpRequest, httpResponse, "User needs to be logged in as system administrator to access this page."); + AuthenticationError.handleError(request, response, "User needs to be logged in as system administrator to access this page."); return; } - httpRequest = new HttpServletRequestWrapper(httpRequest) { + HttpServletRequest httpRequest = new HttpServletRequestWrapper(((JavaxHttpRequest) request).getDelegate()) { @Override public StringBuffer getRequestURL() { return new StringBuffer(oAuth2ContextFactory.generateCallbackUrl(SamlIdentityProvider.KEY)); } }; - httpResponse.setContentType("text/html"); + response.setContentType("text/html"); - String htmlResponse = samlAuthenticator.getAuthenticationStatusPage(httpRequest, httpResponse); - String nonce = SamlValidationCspHeaders.addCspHeadersWithNonceToResponse(httpResponse); + String htmlResponse = samlAuthenticator.getAuthenticationStatusPage(new JavaxHttpRequest(httpRequest), response); + String nonce = SamlValidationCspHeaders.addCspHeadersWithNonceToResponse(response); htmlResponse = htmlResponse.replace("%NONCE%", nonce); - httpResponse.getWriter().print(htmlResponse); + response.getWriter().print(htmlResponse); } @Override diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/saml/ws/ValidationInitAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/saml/ws/ValidationInitAction.java index 6ec10cbf358..9960cb09151 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/saml/ws/ValidationInitAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/saml/ws/ValidationInitAction.java @@ -20,14 +20,12 @@ package org.sonar.server.saml.ws; import java.io.IOException; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import org.sonar.api.server.http.HttpRequest; +import org.sonar.api.server.http.HttpResponse; import org.sonar.api.server.ws.WebService; -import org.sonar.api.web.ServletFilter; +import org.sonar.api.web.FilterChain; +import org.sonar.api.web.HttpFilter; +import org.sonar.api.web.UrlPattern; import org.sonar.auth.saml.SamlAuthenticator; import org.sonar.auth.saml.SamlIdentityProvider; import org.sonar.server.authentication.AuthenticationError; @@ -40,7 +38,7 @@ import org.sonar.server.ws.ServletFilterHandler; import static org.sonar.server.authentication.SamlValidationRedirectionFilter.SAML_VALIDATION_CONTROLLER_CONTEXT; import static org.sonar.server.authentication.SamlValidationRedirectionFilter.SAML_VALIDATION_KEY; -public class ValidationInitAction extends ServletFilter implements SamlAction { +public class ValidationInitAction extends HttpFilter implements SamlAction { public static final String VALIDATION_RELAY_STATE = "validation-query"; public static final String VALIDATION_INIT_KEY = "validation_init"; @@ -73,10 +71,7 @@ public class ValidationInitAction extends ServletFilter implements SamlAction { } @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException { - HttpServletRequest request = (HttpServletRequest) servletRequest; - HttpServletResponse response = (HttpServletResponse) servletResponse; - + public void doFilter(HttpRequest request, HttpResponse response, FilterChain chain) throws IOException { try { userSession.checkIsSystemAdministrator(); } catch (ForbiddenException e) { @@ -84,7 +79,7 @@ public class ValidationInitAction extends ServletFilter implements SamlAction { return; } - String csrfState = oAuthCsrfVerifier.generateState(request,response); + String csrfState = oAuthCsrfVerifier.generateState(request, response); try { samlAuthenticator.initLogin(oAuth2ContextFactory.generateCallbackUrl(SamlIdentityProvider.KEY), diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/ChangePasswordAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/ChangePasswordAction.java index c437c68568e..accc04598a5 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/ChangePasswordAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/ChangePasswordAction.java @@ -25,16 +25,15 @@ import com.google.gson.stream.JsonWriter; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.util.Optional; -import javax.servlet.FilterChain; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import org.sonar.api.server.http.HttpRequest; +import org.sonar.api.server.http.HttpResponse; import org.sonar.api.server.ws.Change; import org.sonar.api.server.ws.WebService; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; -import org.sonar.api.web.ServletFilter; +import org.sonar.api.web.FilterChain; +import org.sonar.api.web.HttpFilter; +import org.sonar.api.web.UrlPattern; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.user.UserDto; @@ -61,7 +60,7 @@ import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_LOGIN; import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_PASSWORD; import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_PREVIOUS_PASSWORD; -public class ChangePasswordAction extends ServletFilter implements BaseUsersWsAction { +public class ChangePasswordAction extends HttpFilter implements BaseUsersWsAction { private static final Logger LOG = Loggers.get(ChangePasswordAction.class); @@ -117,7 +116,7 @@ public class ChangePasswordAction extends ServletFilter implements BaseUsersWsAc } @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { + public void doFilter(HttpRequest request, HttpResponse response, FilterChain chain) { userSession.checkLoggedIn(); try (DbSession dbSession = dbClient.openSession(false)) { String login = getParamOrThrow(request, PARAM_LOGIN); @@ -148,7 +147,7 @@ public class ChangePasswordAction extends ServletFilter implements BaseUsersWsAc } } - private static String getParamOrThrow(ServletRequest request, String key) throws PasswordException { + private static String getParamOrThrow(HttpRequest request, String key) throws PasswordException { String value = request.getParameter(key); if (isNullOrEmpty(value)) { throw new PasswordException(format(MSG_PARAMETER_MISSING, key)); @@ -178,16 +177,14 @@ public class ChangePasswordAction extends ServletFilter implements BaseUsersWsAc return user; } - private void deleteTokensAndRefreshSession(ServletRequest request, ServletResponse response, DbSession dbSession, UserDto user) { + private void deleteTokensAndRefreshSession(HttpRequest request, HttpResponse response, DbSession dbSession, UserDto user) { dbClient.sessionTokensDao().deleteByUser(dbSession, user); refreshJwtToken(request, response, user); } - private void refreshJwtToken(ServletRequest request, ServletResponse response, UserDto user) { - HttpServletRequest httpRequest = (HttpServletRequest) request; - HttpServletResponse httpResponse = (HttpServletResponse) response; - jwtHttpHandler.removeToken(httpRequest, httpResponse); - jwtHttpHandler.generateToken(user, httpRequest, httpResponse); + private void refreshJwtToken(HttpRequest request, HttpResponse response, UserDto user) { + jwtHttpHandler.removeToken(request, response); + jwtHttpHandler.generateToken(user, request, response); } private void updatePassword(DbSession dbSession, UserDto user, String newPassword) { @@ -196,14 +193,15 @@ public class ChangePasswordAction extends ServletFilter implements BaseUsersWsAc }); } - private static void setResponseStatus(ServletResponse response, int newStatusCode) { - ((HttpServletResponse) response).setStatus(newStatusCode); + private static void setResponseStatus(HttpResponse response, int newStatusCode) { + response.setStatus(newStatusCode); } - private static void writeJsonResponse(String msg, ServletResponse response) { + private static void writeJsonResponse(String msg, HttpResponse response) { Gson gson = new GsonBuilder() .disableHtmlEscaping() .create(); + try (OutputStream output = response.getOutputStream(); JsonWriter writer = gson.newJsonWriter(new OutputStreamWriter(output, UTF_8))) { response.setContentType(JSON); diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/authentication/ws/LogoutActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/authentication/ws/LogoutActionTest.java index bb7f24fe945..168c29d9335 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/authentication/ws/LogoutActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/authentication/ws/LogoutActionTest.java @@ -21,14 +21,11 @@ package org.sonar.server.authentication.ws; import java.util.Collections; import java.util.Optional; -import javax.servlet.FilterChain; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.junit.Rule; import org.junit.Test; +import org.sonar.api.server.http.HttpRequest; +import org.sonar.api.server.http.HttpResponse; import org.sonar.api.server.ws.WebService; -import org.sonar.api.utils.System2; -import org.sonar.db.DbTester; +import org.sonar.api.web.FilterChain; import org.sonar.db.user.UserDto; import org.sonar.server.authentication.JwtHttpHandler; import org.sonar.server.authentication.event.AuthenticationEvent; @@ -49,15 +46,14 @@ public class LogoutActionTest { private static final UserDto USER = newUserDto().setLogin("john"); + private final HttpRequest request = mock(HttpRequest.class); + private final HttpResponse response = mock(HttpResponse.class); + private final FilterChain chain = mock(FilterChain.class); - private HttpServletRequest request = mock(HttpServletRequest.class); - private HttpServletResponse response = mock(HttpServletResponse.class); - private FilterChain chain = mock(FilterChain.class); + private final JwtHttpHandler jwtHttpHandler = mock(JwtHttpHandler.class); + private final AuthenticationEvent authenticationEvent = mock(AuthenticationEvent.class); - private JwtHttpHandler jwtHttpHandler = mock(JwtHttpHandler.class); - private AuthenticationEvent authenticationEvent = mock(AuthenticationEvent.class); - - private LogoutAction underTest = new LogoutAction(jwtHttpHandler, authenticationEvent); + private final LogoutAction underTest = new LogoutAction(jwtHttpHandler, authenticationEvent); @Test public void verify_definition() { @@ -119,12 +115,12 @@ public class LogoutActionTest { public void generate_auth_event_on_failure() { setUser(USER); AuthenticationException exception = AuthenticationException.newBuilder().setMessage("error!").setSource(sso()).build(); - doThrow(exception).when(jwtHttpHandler).getToken(any(HttpServletRequest.class), any(HttpServletResponse.class)); + doThrow(exception).when(jwtHttpHandler).getToken(any(HttpRequest.class), any(HttpResponse.class)); executeRequest(); verify(authenticationEvent).logoutFailure(request, "error!"); - verify(jwtHttpHandler).removeToken(any(HttpServletRequest.class), any(HttpServletResponse.class)); + verify(jwtHttpHandler).removeToken(any(HttpRequest.class), any(HttpResponse.class)); verifyNoInteractions(chain); } @@ -134,12 +130,12 @@ public class LogoutActionTest { } private void setUser(UserDto user) { - when(jwtHttpHandler.getToken(any(HttpServletRequest.class), any(HttpServletResponse.class))) + when(jwtHttpHandler.getToken(any(HttpRequest.class), any(HttpResponse.class))) .thenReturn(Optional.of(new JwtHttpHandler.Token(user, Collections.emptyMap()))); } private void setNoUser() { - when(jwtHttpHandler.getToken(any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(Optional.empty()); + when(jwtHttpHandler.getToken(any(HttpRequest.class), any(HttpResponse.class))).thenReturn(Optional.empty()); } } diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/authentication/ws/ValidateActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/authentication/ws/ValidateActionTest.java index b6258f62367..f41f4797cdf 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/authentication/ws/ValidateActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/authentication/ws/ValidateActionTest.java @@ -22,13 +22,13 @@ package org.sonar.server.authentication.ws; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Optional; -import javax.servlet.FilterChain; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import org.junit.Before; import org.junit.Test; import org.sonar.api.config.internal.MapSettings; +import org.sonar.api.server.http.HttpRequest; +import org.sonar.api.server.http.HttpResponse; import org.sonar.api.server.ws.WebService; +import org.sonar.api.web.FilterChain; import org.sonar.server.authentication.BasicAuthentication; import org.sonar.server.authentication.JwtHttpHandler; import org.sonar.server.authentication.event.AuthenticationException; @@ -45,18 +45,18 @@ import static org.sonar.db.user.UserTesting.newUserDto; public class ValidateActionTest { - StringWriter stringWriter = new StringWriter(); + private final StringWriter stringWriter = new StringWriter(); - HttpServletRequest request = mock(HttpServletRequest.class); - HttpServletResponse response = mock(HttpServletResponse.class); - FilterChain chain = mock(FilterChain.class); + private final HttpRequest request = mock(HttpRequest.class); + private final HttpResponse response = mock(HttpResponse.class); + private final FilterChain chain = mock(FilterChain.class); - BasicAuthentication basicAuthentication = mock(BasicAuthentication.class); - JwtHttpHandler jwtHttpHandler = mock(JwtHttpHandler.class); + private final BasicAuthentication basicAuthentication = mock(BasicAuthentication.class); + private final JwtHttpHandler jwtHttpHandler = mock(JwtHttpHandler.class); - MapSettings settings = new MapSettings(); + private final MapSettings settings = new MapSettings(); - ValidateAction underTest = new ValidateAction(settings.asConfig(), basicAuthentication, jwtHttpHandler); + private final ValidateAction underTest = new ValidateAction(settings.asConfig(), basicAuthentication, jwtHttpHandler); @Before public void setUp() throws Exception { diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/saml/ws/ValidationActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/saml/ws/ValidationActionTest.java index 659f9dc956a..8e293ee5639 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/saml/ws/ValidationActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/saml/ws/ValidationActionTest.java @@ -23,20 +23,22 @@ import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.util.List; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.junit.Before; import org.junit.Test; +import org.sonar.api.server.http.HttpRequest; +import org.sonar.api.server.http.HttpResponse; import org.sonar.api.server.ws.WebService; +import org.sonar.api.web.FilterChain; import org.sonar.auth.saml.SamlAuthenticator; import org.sonar.auth.saml.SamlIdentityProvider; import org.sonar.server.authentication.OAuth2ContextFactory; import org.sonar.server.authentication.OAuthCsrfVerifier; -import org.sonar.server.authentication.SamlValidationCspHeaders; import org.sonar.server.authentication.event.AuthenticationEvent; import org.sonar.server.authentication.event.AuthenticationException; +import org.sonar.server.http.JavaxHttpRequest; +import org.sonar.server.http.JavaxHttpResponse; import org.sonar.server.user.ThreadLocalUserSession; import static org.assertj.core.api.Assertions.assertThat; @@ -70,7 +72,6 @@ public class ValidationActionTest { underTest = new ValidationAction(userSession, samlAuthenticator, oAuth2ContextFactory, samlIdentityProvider, oAuthCsrfVerifier); } - @Test public void do_get_pattern() { assertThat(underTest.doGetPattern().matches("/saml/validation")).isTrue(); @@ -81,8 +82,8 @@ public class ValidationActionTest { } @Test - public void do_filter_admin() throws ServletException, IOException { - HttpServletRequest servletRequest = mock(HttpServletRequest.class); + public void do_filter_admin() throws IOException { + HttpServletRequest servletRequest = spy(HttpServletRequest.class); HttpServletResponse servletResponse = mock(HttpServletResponse.class); StringWriter stringWriter = new StringWriter(); doReturn(new PrintWriter(stringWriter)).when(servletResponse).getWriter(); @@ -93,7 +94,7 @@ public class ValidationActionTest { final String mockedHtmlContent = "mocked html content"; doReturn(mockedHtmlContent).when(samlAuthenticator).getAuthenticationStatusPage(any(), any()); - underTest.doFilter(servletRequest, servletResponse, filterChain); + underTest.doFilter(new JavaxHttpRequest(servletRequest), new JavaxHttpResponse(servletResponse), filterChain); verify(samlAuthenticator).getAuthenticationStatusPage(any(), any()); verify(servletResponse).getWriter(); @@ -102,9 +103,9 @@ public class ValidationActionTest { } @Test - public void do_filter_not_authorized() throws ServletException, IOException { - HttpServletRequest servletRequest = spy(HttpServletRequest.class); - HttpServletResponse servletResponse = mock(HttpServletResponse.class); + public void do_filter_not_authorized() throws IOException { + HttpRequest servletRequest = spy(HttpRequest.class); + HttpResponse servletResponse = mock(HttpResponse.class); StringWriter stringWriter = new StringWriter(); doReturn(new PrintWriter(stringWriter)).when(servletResponse).getWriter(); FilterChain filterChain = mock(FilterChain.class); @@ -118,9 +119,9 @@ public class ValidationActionTest { } @Test - public void do_filter_failed_csrf_verification() throws ServletException, IOException { - HttpServletRequest servletRequest = spy(HttpServletRequest.class); - HttpServletResponse servletResponse = mock(HttpServletResponse.class); + public void do_filter_failed_csrf_verification() throws IOException { + HttpRequest servletRequest = spy(HttpRequest.class); + HttpResponse servletResponse = mock(HttpResponse.class); StringWriter stringWriter = new StringWriter(); doReturn(new PrintWriter(stringWriter)).when(servletResponse).getWriter(); FilterChain filterChain = mock(FilterChain.class); @@ -128,7 +129,7 @@ public class ValidationActionTest { doReturn("IdentityProviderName").when(samlIdentityProvider).getName(); doThrow(AuthenticationException.newBuilder() .setSource(AuthenticationEvent.Source.oauth2(samlIdentityProvider)) - .setMessage("Cookie is missing").build()).when(oAuthCsrfVerifier).verifyState(any(),any(),any(), any()); + .setMessage("Cookie is missing").build()).when(oAuthCsrfVerifier).verifyState(any(), any(), any(), any()); doReturn(true).when(userSession).hasSession(); doReturn(true).when(userSession).isSystemAdministrator(); diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/saml/ws/ValidationInitActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/saml/ws/ValidationInitActionTest.java index 5f205f3da56..5a6db55a32e 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/saml/ws/ValidationInitActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/saml/ws/ValidationInitActionTest.java @@ -20,14 +20,13 @@ package org.sonar.server.saml.ws; import java.io.IOException; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.sonar.api.server.http.HttpRequest; +import org.sonar.api.server.http.HttpResponse; import org.sonar.api.server.ws.WebService; +import org.sonar.api.web.FilterChain; import org.sonar.auth.saml.SamlAuthenticator; import org.sonar.server.authentication.OAuth2ContextFactory; import org.sonar.server.authentication.OAuthCsrfVerifier; @@ -68,10 +67,10 @@ public class ValidationInitActionTest { } @Test - public void do_filter_as_admin() throws IOException, ServletException { + public void do_filter_as_admin() throws IOException { userSession.logIn().setSystemAdministrator(); - HttpServletRequest servletRequest = mock(HttpServletRequest.class); - HttpServletResponse servletResponse = mock(HttpServletResponse.class); + HttpRequest servletRequest = mock(HttpRequest.class); + HttpResponse servletResponse = mock(HttpResponse.class); FilterChain filterChain = mock(FilterChain.class); String callbackUrl = "http://localhost:9000/api/validation_test"; @@ -86,10 +85,10 @@ public class ValidationInitActionTest { } @Test - public void do_filter_as_admin_with_init_issues() throws IOException, ServletException { + public void do_filter_as_admin_with_init_issues() throws IOException { userSession.logIn().setSystemAdministrator(); - HttpServletRequest servletRequest = mock(HttpServletRequest.class); - HttpServletResponse servletResponse = mock(HttpServletResponse.class); + HttpRequest servletRequest = mock(HttpRequest.class); + HttpResponse servletResponse = mock(HttpResponse.class); FilterChain filterChain = mock(FilterChain.class); String callbackUrl = "http://localhost:9000/api/validation_test"; when(oAuth2ContextFactory.generateCallbackUrl(anyString())) @@ -104,10 +103,10 @@ public class ValidationInitActionTest { } @Test - public void do_filter_as_not_admin() throws IOException, ServletException { + public void do_filter_as_not_admin() throws IOException { userSession.logIn(); - HttpServletRequest servletRequest = mock(HttpServletRequest.class); - HttpServletResponse servletResponse = mock(HttpServletResponse.class); + HttpRequest servletRequest = mock(HttpRequest.class); + HttpResponse servletResponse = mock(HttpResponse.class); FilterChain filterChain = mock(FilterChain.class); String callbackUrl = "http://localhost:9000/api/validation_test"; when(oAuth2ContextFactory.generateCallbackUrl(anyString())) @@ -120,10 +119,10 @@ public class ValidationInitActionTest { } @Test - public void do_filter_as_anonymous() throws IOException, ServletException { + public void do_filter_as_anonymous() throws IOException { userSession.anonymous(); - HttpServletRequest servletRequest = mock(HttpServletRequest.class); - HttpServletResponse servletResponse = mock(HttpServletResponse.class); + HttpRequest servletRequest = mock(HttpRequest.class); + HttpResponse servletResponse = mock(HttpResponse.class); FilterChain filterChain = mock(FilterChain.class); String callbackUrl = "http://localhost:9000/api/validation_test"; when(oAuth2ContextFactory.generateCallbackUrl(anyString())) @@ -149,7 +148,7 @@ public class ValidationInitActionTest { assertThat(validationInitAction.handler()).isNotNull(); } - private void mockCsrfTokenGeneration(HttpServletRequest servletRequest, HttpServletResponse servletResponse) { + private void mockCsrfTokenGeneration(HttpRequest servletRequest, HttpResponse servletResponse) { when(oAuthCsrfVerifier.generateState(servletRequest, servletResponse)).thenReturn("CSRF_TOKEN"); } } |