Send error with message from Endpoint MVC security
Update `MvcEndpointSecurityInterceptor` to that it sends an error in the same way as Spring Security. Prior to this commit the `ErrorController` would not handle endpoint security errors. Fixes gh-7605 Closes gh-7634
This commit is contained in:
committed by
Phillip Webb
parent
9aaae808a6
commit
38eeae2166
@@ -59,17 +59,25 @@ public class MvcEndpointSecurityInterceptor extends HandlerInterceptorAdapter {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
setFailureResponseStatus(request, response);
|
||||
sendFailureResponse(request, response);
|
||||
return false;
|
||||
}
|
||||
|
||||
private void setFailureResponseStatus(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
private void sendFailureResponse(HttpServletRequest request,
|
||||
HttpServletResponse response) throws Exception {
|
||||
if (request.getUserPrincipal() != null) {
|
||||
response.setStatus(HttpStatus.FORBIDDEN.value());
|
||||
StringBuilder message = new StringBuilder();
|
||||
for (String role : this.roles) {
|
||||
message.append(role).append(" ");
|
||||
}
|
||||
response.sendError(HttpStatus.FORBIDDEN.value(),
|
||||
"Access is denied. User must have one of the these roles: "
|
||||
+ message.toString().trim());
|
||||
}
|
||||
else {
|
||||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||
response.sendError(HttpStatus.UNAUTHORIZED.value(),
|
||||
"Full authentication is required to access this resource. "
|
||||
+ "Consider adding Spring Security or set management.security.enabled to false.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,19 +16,24 @@
|
||||
|
||||
package org.springframework.boot.actuate.endpoint.mvc;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Tests for {@link MvcEndpointSecurityInterceptor}.
|
||||
@@ -47,7 +52,7 @@ public class MvcEndpointSecurityInterceptorTests {
|
||||
|
||||
private MockHttpServletRequest request;
|
||||
|
||||
private MockHttpServletResponse response;
|
||||
private HttpServletResponse response;
|
||||
|
||||
private MockServletContext servletContext;
|
||||
|
||||
@@ -62,7 +67,7 @@ public class MvcEndpointSecurityInterceptorTests {
|
||||
this.handlerMethod = new HandlerMethod(this.mvcEndpoint, "invoke");
|
||||
this.servletContext = new MockServletContext();
|
||||
this.request = new MockHttpServletRequest(this.servletContext);
|
||||
this.response = new MockHttpServletResponse();
|
||||
this.response = mock(HttpServletResponse.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -87,11 +92,25 @@ public class MvcEndpointSecurityInterceptorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sensitiveEndpointIfRoleIsNotPresentShouldNotAllowAccess()
|
||||
public void sensitiveEndpointIfNotAuthenticatedShouldNotAllowAccess()
|
||||
throws Exception {
|
||||
assertThat(this.securityInterceptor.preHandle(this.request, this.response,
|
||||
this.handlerMethod)).isFalse();
|
||||
verify(this.response).sendError(HttpStatus.UNAUTHORIZED.value(),
|
||||
"Full authentication is required to access this resource. "
|
||||
+ "Consider adding Spring Security or set management.security.enabled to false.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sensitiveEndpointIfRoleIsNotCorrectShouldNotAllowAccess()
|
||||
throws Exception {
|
||||
Principal principal = mock(Principal.class);
|
||||
this.request.setUserPrincipal(principal);
|
||||
this.servletContext.declareRoles("HERO");
|
||||
assertThat(this.securityInterceptor.preHandle(this.request, this.response,
|
||||
this.handlerMethod)).isFalse();
|
||||
verify(this.response).sendError(HttpStatus.FORBIDDEN.value(),
|
||||
"Access is denied. User must have one of the these roles: SUPER_HERO");
|
||||
}
|
||||
|
||||
private static class TestEndpoint extends AbstractEndpoint<Object> {
|
||||
|
||||
Reference in New Issue
Block a user