GUACAMOLE-566: Handle all exceptions, not just GuacamoleException instances.

This commit is contained in:
Nick Couchman
2018-05-29 22:13:04 -04:00
parent 75c8fc856b
commit a3faf6a2ee
2 changed files with 34 additions and 27 deletions

View File

@@ -21,18 +21,12 @@ package org.apache.guacamole.rest;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Singleton; import com.google.inject.Singleton;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Map;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.FormParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context; import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider; import javax.ws.rs.ext.Provider;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleUnauthorizedException; import org.apache.guacamole.GuacamoleUnauthorizedException;
import org.apache.guacamole.rest.auth.AuthenticationService; import org.apache.guacamole.rest.auth.AuthenticationService;
@@ -46,18 +40,18 @@ import org.slf4j.LoggerFactory;
*/ */
@Provider @Provider
@Singleton @Singleton
public class GuacamoleExceptionMapper public class RESTExceptionMapper implements ExceptionMapper<Throwable> {
implements ExceptionMapper<GuacamoleException> {
/** /**
* The logger for this class. * The logger for this class.
*/ */
private final Logger logger = LoggerFactory.getLogger(GuacamoleExceptionMapper.class); private final Logger logger = LoggerFactory.getLogger(RESTExceptionMapper.class);
/** /**
* The request associated with this instance of this mapper. * The request associated with this instance of this mapper.
*/ */
@Context private HttpServletRequest request; @Context
private HttpServletRequest request;
/** /**
* The authentication service associated with the currently active session. * The authentication service associated with the currently active session.
@@ -75,34 +69,47 @@ public class GuacamoleExceptionMapper
*/ */
private String getAuthenticationToken() { private String getAuthenticationToken() {
@SuppressWarnings("unchecked") String token = request.getParameter("token");
Map<String, String[]> parameters = request.getParameterMap(); if (token != null && !token.isEmpty())
return token;
for (String paramName : parameters.keySet()) {
if (paramName.equals("token")) {
String tokenParams[] = parameters.get(paramName);
if (tokenParams[0] != null && !tokenParams[0].isEmpty())
return tokenParams[0];
}
}
return null; return null;
} }
@Override @Override
public Response toResponse(GuacamoleException e) { public Response toResponse(Throwable t) {
if (e instanceof GuacamoleUnauthorizedException) { // Ensure any associated session is invalidated if unauthorized
if (t instanceof GuacamoleUnauthorizedException) {
String token = getAuthenticationToken(); String token = getAuthenticationToken();
if (authenticationService.destroyGuacamoleSession(token)) if (authenticationService.destroyGuacamoleSession(token))
logger.debug("Implicitly invalidated session for token \"{}\"", token); logger.debug("Implicitly invalidated session for token \"{}\"", token);
} }
// Translate GuacamoleException subclasses to HTTP error codes
if (t instanceof GuacamoleException)
return Response return Response
.status(e.getHttpStatusCode()) .status(((GuacamoleException) t).getHttpStatusCode())
.entity(new APIError(e)) .entity(new APIError((GuacamoleException)t))
.type(MediaType.APPLICATION_JSON)
.build();
// Rethrow unchecked exceptions such that they are properly wrapped
String message = t.getMessage();
if (message != null)
logger.error("Unexpected internal error: {}", message);
else
logger.error("An internal error occurred, but did not contain "
+ "an error message. Enable debug-level logging for "
+ "details.");
logger.debug("Unexpected error in REST endpoint.", t);
return Response
.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Unexpected Internal Error.")
.type(MediaType.APPLICATION_JSON) .type(MediaType.APPLICATION_JSON)
.build(); .build();

View File

@@ -84,8 +84,8 @@ public class RESTServiceModule extends ServletModule {
bind(AuthTokenGenerator.class).to(SecureRandomAuthTokenGenerator.class); bind(AuthTokenGenerator.class).to(SecureRandomAuthTokenGenerator.class);
bind(DecorationService.class); bind(DecorationService.class);
// Get the ExceptionMapper that will rewrite exceptions into JSON. // Automatically translate GuacamoleExceptions for REST methods
bind(GuacamoleExceptionMapper.class); bind(RESTExceptionMapper.class);
// Set up the API endpoints // Set up the API endpoints
bind(ExtensionRESTService.class); bind(ExtensionRESTService.class);