package org.deegree.securityproxy.wms.authorization;
import static org.deegree.securityproxy.wms.request.WmsRequestParser.GETCAPABILITIES;
import static org.deegree.securityproxy.wms.request.WmsRequestParser.GETFEATUREINFO;
import static org.deegree.securityproxy.wms.request.WmsRequestParser.GETMAP;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.deegree.securityproxy.authentication.ows.domain.LimitedOwsServiceVersion;
import org.deegree.securityproxy.authentication.ows.raster.RasterPermission;
import org.deegree.securityproxy.authorization.RequestAuthorizationManager;
import org.deegree.securityproxy.authorization.logging.AuthorizationReport;
import org.deegree.securityproxy.request.OwsRequest;
import org.deegree.securityproxy.request.OwsServiceVersion;
import org.deegree.securityproxy.wms.request.WmsRequest;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
/**
* Checks if a authenticated User is permitted to perform an incoming {@link javax.servlet.http.HttpServletRequest}
* against a WMS.
*
* @author <a href="stenger@lat-lon.de">Dirk Stenger</a>
* @author last edited by: $Author: stenger $
* @version $Revision: $, $Date: $
*/
public class WmsRequestAuthorizationManager implements RequestAuthorizationManager {
public static final boolean AUTHORIZED = true;
private static final String NOT_AUTHENTICATED_ERROR_MSG = "Error while retrieving authentication! "
+ "User could not be authenticated.";
private static final String ACCESS_GRANTED_MSG = "Access granted.";
private static final String UNKNOWN_ERROR_MSG = "Unknown error. See application log for details.";
private static final String GETFEATUREINFO_UNAUTHORIZED_MSG = "User not permitted to perform operation "
+ "GetFeatureInfo with the given parameters";
public static final String GETMAP_UNAUTHORIZED_MSG = "User not permitted to perform operation GetMap "
+ "with the given parameters";
public static final String GETCAPABILITIES_UNAUTHORIZED_MSG = "User not permitted to perform operation "
+ "GetCapabilities with the given parameters";
@Override
public AuthorizationReport decide( Authentication authentication, OwsRequest request ) {
if ( !checkAuthentication( authentication ) ) {
return new AuthorizationReport( NOT_AUTHENTICATED_ERROR_MSG );
}
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
WmsRequest wmsRequest = (WmsRequest) request;
if ( isGetMapRequest( wmsRequest ) ) {
return authorizeGetMap( wmsRequest, authorities );
} else if ( isGetFeatureInfoRequest( wmsRequest ) ) {
return authorizeGetFeatureInfo( wmsRequest, authorities );
} else if ( isGetCapabilitiesRequest( wmsRequest ) ) {
return authorizeGetCapabilities( wmsRequest, authorities );
}
return new AuthorizationReport( UNKNOWN_ERROR_MSG );
}
private boolean checkAuthentication( Authentication authentication ) {
return !( authentication instanceof AnonymousAuthenticationToken );
}
@Override
public boolean supports( Class<?> clazz ) {
return WmsRequest.class.equals( clazz );
}
private AuthorizationReport authorizeGetFeatureInfo( WmsRequest wmsRequest,
Collection<? extends GrantedAuthority> authorities ) {
List<String> grantedLayers = new ArrayList<String>();
String internalServiceUrl = null;
Map<String, String[]> additionalKeyValuePairs = null;
for ( GrantedAuthority authority : authorities ) {
if ( authority instanceof RasterPermission ) {
RasterPermission wmsPermission = (RasterPermission) authority;
if ( areCommonParamsAuthorized( wmsRequest, wmsPermission ) ) {
grantedLayers.add( wmsPermission.getLayerName() );
// If there are data inconsistencies and a service-name is mapped to different internal-urls, the
// DSP always chooses the url of the last permission.
internalServiceUrl = wmsPermission.getInternalServiceUrl();
additionalKeyValuePairs = wmsPermission.getAdditionalKeyValuePairs();
}
}
}
for ( String layerName : wmsRequest.getLayerNames() ) {
if ( !grantedLayers.contains( layerName ) )
return new AuthorizationReport( GETFEATUREINFO_UNAUTHORIZED_MSG );
}
for ( String queryLayerName : wmsRequest.getQueryLayerNames() ) {
if ( !grantedLayers.contains( queryLayerName ) )
return new AuthorizationReport( GETFEATUREINFO_UNAUTHORIZED_MSG );
}
return new AuthorizationReport( ACCESS_GRANTED_MSG, AUTHORIZED, internalServiceUrl, additionalKeyValuePairs );
}
private AuthorizationReport authorizeGetMap( WmsRequest wmsRequest,
Collection<? extends GrantedAuthority> authorities ) {
List<String> grantedLayers = new ArrayList<String>();
String internalServiceUrl = null;
Map<String, String[]> additionalKeyValuePairs = null;
for ( GrantedAuthority authority : authorities ) {
if ( authority instanceof RasterPermission ) {
RasterPermission wmsPermission = (RasterPermission) authority;
if ( areCommonParamsAuthorized( wmsRequest, wmsPermission ) ) {
grantedLayers.add( wmsPermission.getLayerName() );
// If there are data inconsistencies and a service-name is mapped to different internal-urls, the
// DSP always chooses the url of the last permission.
internalServiceUrl = wmsPermission.getInternalServiceUrl();
additionalKeyValuePairs = wmsPermission.getAdditionalKeyValuePairs();
}
}
}
for ( String layerName : wmsRequest.getLayerNames() ) {
if ( !grantedLayers.contains( layerName ) )
return new AuthorizationReport( GETMAP_UNAUTHORIZED_MSG );
}
return new AuthorizationReport( ACCESS_GRANTED_MSG, AUTHORIZED, internalServiceUrl, additionalKeyValuePairs );
}
private AuthorizationReport authorizeGetCapabilities( WmsRequest wmsRequest,
Collection<? extends GrantedAuthority> authorities ) {
for ( GrantedAuthority authority : authorities ) {
if ( authority instanceof RasterPermission ) {
RasterPermission wmsPermission = (RasterPermission) authority;
if ( areCommonParamsAuthorized( wmsRequest, wmsPermission ) ) {
return createAuthorizedReport( wmsPermission );
}
}
}
return new AuthorizationReport( GETCAPABILITIES_UNAUTHORIZED_MSG );
}
private AuthorizationReport createAuthorizedReport( RasterPermission wmsPermission ) {
String internalServiceUrl = wmsPermission.getInternalServiceUrl();
Map<String, String[]> additionalKVPs = wmsPermission.getAdditionalKeyValuePairs();
return new AuthorizationReport( ACCESS_GRANTED_MSG, AUTHORIZED, internalServiceUrl, additionalKVPs );
}
private boolean areCommonParamsAuthorized( WmsRequest wmsRequest, RasterPermission wmsPermission ) {
return isServiceTypeAuthorized( wmsRequest, wmsPermission )
&& isOperationTypeAuthorized( wmsRequest, wmsPermission )
&& isServiceVersionAuthorized( wmsRequest, wmsPermission )
&& isServiceNameAuthorized( wmsRequest, wmsPermission );
}
private boolean isGetFeatureInfoRequest( WmsRequest wmsRequest ) {
return GETFEATUREINFO.equals( wmsRequest.getOperationType() );
}
private boolean isGetMapRequest( WmsRequest wmsRequest ) {
return GETMAP.equals( wmsRequest.getOperationType() );
}
private boolean isGetCapabilitiesRequest( WmsRequest wmsRequest ) {
return GETCAPABILITIES.equals( wmsRequest.getOperationType() );
}
private boolean isServiceTypeAuthorized( WmsRequest wmsRequest, RasterPermission wmsPermission ) {
return wmsRequest.getServiceType() != null
&& wmsRequest.getServiceType().equalsIgnoreCase( wmsPermission.getServiceType() );
}
private boolean isOperationTypeAuthorized( WmsRequest wmsRequest, RasterPermission wmsPermission ) {
return wmsRequest.getOperationType() != null
&& wmsRequest.getOperationType().equalsIgnoreCase( wmsPermission.getOperationType() );
}
private boolean isServiceVersionAuthorized( WmsRequest wmsRequest, RasterPermission wmsPermission ) {
OwsServiceVersion requestedServiceVersion = wmsRequest.getServiceVersion();
if ( requestedServiceVersion == null )
return false;
LimitedOwsServiceVersion serviceVersionLimit = wmsPermission.getServiceVersion();
return serviceVersionLimit.contains( requestedServiceVersion );
}
private boolean isServiceNameAuthorized( WmsRequest wmsRequest, RasterPermission wmsPermission ) {
return wmsRequest.getServiceName() != null
&& wmsRequest.getServiceName().equals( wmsPermission.getServiceName() );
}
}