package restx.servlet;
import com.google.common.base.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import restx.*;
import restx.factory.Component;
import restx.security.RestxPrincipal;
import restx.security.RestxSession;
import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.security.Principal;
import static restx.servlet.ServletModule.SERVLET_PRINCIPAL_CONVERTER;
/**
* Date: 17/12/13
* Time: 23:01
*/
@Component(priority = -180)
public class ServletSecurityFilter implements RestxFilter, RestxHandler {
private static final Logger logger = LoggerFactory.getLogger(ServletSecurityFilter.class);
private final ServletPrincipalConverter servletPrincipalConverter;
public ServletSecurityFilter(
@Named(SERVLET_PRINCIPAL_CONVERTER) ServletPrincipalConverter servletPrincipalConverter) {
this.servletPrincipalConverter = servletPrincipalConverter;
}
@Override
public Optional<RestxHandlerMatch> match(RestxRequest req) {
try {
HttpServletRequest httpServletRequest = req.unwrap(HttpServletRequest.class);
if (httpServletRequest.getUserPrincipal() != null) {
return Optional.of(new RestxHandlerMatch(
new StdRestxRequestMatch("*", req.getRestxPath()),
this));
} else {
return Optional.absent();
}
} catch (IllegalArgumentException ex) {
return Optional.absent();
} catch (NoClassDefFoundError e) {
if ("javax/servlet/http/HttpServletRequest".equals(e.getMessage())) {
// this may happen when app depends on restx-servlet to have servlet support, but is run outside a servlet container
// eg with restx-simple-server. In this case the provided dependency on servlet API (that is provided by
// the servlet container when run inside such container) will make us fail with a NoClassDefFoundError
return Optional.absent();
} else {
throw e;
}
}
}
@Override
public void handle(RestxRequestMatch match, RestxRequest req, RestxResponse resp, RestxContext ctx) throws IOException {
HttpServletRequest httpServletRequest = req.unwrap(HttpServletRequest.class);
final Principal userPrincipal = httpServletRequest.getUserPrincipal();
if (userPrincipal != null) {
logger.debug("setting restx principal from http servlet request {}", userPrincipal);
if (userPrincipal instanceof RestxPrincipal) {
RestxSession.current().authenticateAs((RestxPrincipal) userPrincipal);
} else {
RestxSession.current().authenticateAs(servletPrincipalConverter.toRestxPrincipal(userPrincipal));
}
}
ctx.nextHandlerMatch().handle(req, resp, ctx);
}
}