/******************************************************************************* * Australian National University Data Commons * Copyright (C) 2013 The Australian National University * * This file is part of Australian National University Data Commons. * * Australian National University Data Commons is free software: you * can redistribute it and/or modify it under the terms of the GNU * General Public License as published by the Free Software Foundation, * either version 3 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package au.edu.anu.datacommons.exception; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import com.sun.jersey.api.view.Viewable; /** * @author Rahul Khanna * */ @Provider public class AccessDeniedExceptionMapper implements ExceptionMapper<AccessDeniedException> { private static final Logger LOGGER = LoggerFactory.getLogger(AccessDeniedExceptionMapper.class); @Context private HttpHeaders headers; @Context protected HttpServletRequest request; @Override public Response toResponse(AccessDeniedException exception) { Response resp; LOGGER.warn("User {} ({}) requested a resource to which they don't have access: {}", getCurUsername(), getRemoteIp(), exception.getMessage()); List<MediaType> acceptableTypes = headers.getAcceptableMediaTypes(); if (acceptableTypes.contains(MediaType.TEXT_HTML_TYPE) || acceptableTypes.contains(MediaType.WILDCARD_TYPE)) { //Present an unauthorized error page if the user is authenticated and not anonymous, otherwise allow the user to log in if (SecurityContextHolder.getContext().getAuthentication() != null && SecurityContextHolder.getContext().getAuthentication().isAuthenticated() && !(SecurityContextHolder.getContext().getAuthentication() instanceof AnonymousAuthenticationToken)) { Map<String, Object> model = new HashMap<String, Object>(); model.put("messages", exception.getMessage()); Viewable viewable = new Viewable("/error.jsp", model); resp = Response.status(Status.UNAUTHORIZED).entity(viewable).build(); } else { resp = Response.status(Status.UNAUTHORIZED).entity(new Viewable("/login_select.jsp")).build(); } } else { resp = Response.status(Status.UNAUTHORIZED).entity(exception.getMessage()).build(); } return resp; } private String getCurUsername() { return SecurityContextHolder.getContext().getAuthentication().getName(); } protected String getRemoteIp() { return request.getRemoteAddr(); } }