public boolean doThrottle( HttpServletRequest request, APIKeyValidationInfoDTO apiKeyValidationInfoDTO, String accessToken) { ThrottleManager throttleManager = new ThrottleManager(id, key); ConfigurationContext cc = DataHolder.getServerConfigContext(); ClusteringAgent clusteringAgent = cc.getAxisConfiguration().getClusteringAgent(); if (clusteringAgent != null && clusteringAgent.getStateManager() != null) { isClusteringEnable = true; } // check the availability of the ConcurrentAccessController // if this is a clustered environment if (isClusteringEnable) { concurrentAccessController = (ConcurrentAccessController) cc.getProperty(key); } initThrottle(cc); // perform concurrency throttling boolean canAccess = throttleManager.doThrottleByConcurrency(false, concurrentAccessController); if (canAccess) { String remoteIP = request.getRemoteAddr(); canAccess = throttleManager.throttleByAccessRate( remoteIP, remoteIP, cc, isClusteringEnable, concurrentAccessController, throttle) && throttleManager.doRoleBasedAccessThrottling( isClusteringEnable, cc, apiKeyValidationInfoDTO, accessToken, throttle); } // All the replication functionality of the access rate based throttling handled by itself // Just replicate the current state of ConcurrentAccessController if (isClusteringEnable && concurrentAccessController != null) { if (cc != null) { try { Replicator.replicate(cc); } catch (ClusteringFault clusteringFault) { handleException("Error during the replicating states ", clusteringFault); } } } if (!canAccess) { return false; } return true; }
/** * Helper method to replicates states of the property with given key Removes the property and then * replicates the current state so that all instances across cluster can see this state * * @param key The key of the property * @param configCtx Axis2 configuration context */ public static void removeAndReplicateState(String key, ConfigurationContext configCtx) { if (configCtx != null && key != null) { try { if (log.isDebugEnabled()) { log.debug("Start replicating the property removal with key : " + key); } configCtx.removePropertyNonReplicable(key); org.apache.axis2.clustering.state.Replicator.replicate(configCtx, new String[] {key}); if (log.isDebugEnabled()) { log.debug("Completed replication of the property removal with key : " + key); } } catch (ClusteringFault clusteringFault) { handleException("Error during the replicating states ", clusteringFault); } } }
/** * Helper method for handling role based Access throttling * * @param messageContext MessageContext - message level states * @return true if access is allowed through concurrent throttling ,o.w false */ private boolean doRoleBasedAccessThrottling( Throttle throttle, MessageContext messageContext, boolean isClusteringEnable) throws AxisFault, ThrottleException { boolean canAccess = true; ConfigurationContext cc = messageContext.getConfigurationContext(); String throttleId = throttle.getId(); String key = null; ConcurrentAccessController cac = null; if (isClusteringEnable) { // for clustered env.,gets it from axis configuration context key = ThrottleConstants.THROTTLE_PROPERTY_PREFIX + throttleId + ThrottleConstants.CAC_SUFFIX; cac = (ConcurrentAccessController) cc.getProperty(key); } if (messageContext.getFLOW() == MessageContext.IN_FLOW) { // gets the remote caller role name String consumerKey = null; boolean isAuthenticated = false; String roleID = null; HttpServletRequest request = (HttpServletRequest) messageContext.getPropertyNonReplicable(HTTPConstants.MC_HTTP_SERVLETREQUEST); if (request != null) { String oAuthHeader = request.getHeader("OAuth"); // consumerKey = Utils.extractCustomerKeyFromAuthHeader(oAuthHeader); // roleID = Utils.extractCustomerKeyFromAuthHeader(oAuthHeader); DummyAuthenticator authFuture = new DummyAuthenticator(oAuthHeader); consumerKey = authFuture.getAPIKey(); new DummyHandler().authenticateUser(authFuture); roleID = (String) authFuture.getAuthorizedRoles().get(0); isAuthenticated = authFuture.isAuthenticated(); } if (!isAuthenticated) { throw new AxisFault( " Access deny for a " + "caller with consumer Key: " + consumerKey + " " + " : Reason : Authentication failure"); } // Domain name based throttling // check whether a configuration has been defined for this role name or not String consumerRoleID = null; if (consumerKey != null && isAuthenticated) { // loads the ThrottleContext ThrottleContext context = throttle.getThrottleContext(ThrottleConstants.ROLE_BASED_THROTTLE_KEY); if (context != null) { // Loads the ThrottleConfiguration ThrottleConfiguration config = context.getThrottleConfiguration(); if (config != null) { // check for configuration for this caller consumerRoleID = config.getConfigurationKeyOfCaller(roleID); if (consumerRoleID != null) { // If this is a clustered env. if (isClusteringEnable) { context.setConfigurationContext(cc); context.setThrottleId(throttleId); } AccessInformation infor = roleBasedAccessController.canAccess(context, consumerKey, consumerRoleID); StatCollector.collect(infor, consumerKey, ThrottleConstants.ROLE_BASE); // check for the permission for access if (!infor.isAccessAllowed()) { // In the case of both of concurrency throttling and // rate based throttling have enabled , // if the access rate less than maximum concurrent access , // then it is possible to occur death situation.To avoid that reset, // if the access has denied by rate based throttling if (cac != null) { cac.incrementAndGet(); // set back if this is a clustered env if (isClusteringEnable) { cc.setProperty(key, cac); // replicate the current state of ConcurrentAccessController try { if (debugOn) { log.debug( "Going to replicates the " + "states of the ConcurrentAccessController" + " with key : " + key); } Replicator.replicate(cc, new String[] {key}); } catch (ClusteringFault clusteringFault) { log.error("Error during replicating states ", clusteringFault); } } } throw new AxisFault( " Access deny for a " + "caller with Domain " + consumerKey + " " + " : Reason : " + infor.getFaultReason()); } } else { if (debugOn) { log.debug( "Could not find the Throttle Context for role-Based " + "Throttling for role name " + consumerKey + " Throttling for this " + "role name may not be configured from policy"); } } } } } else { if (debugOn) { log.debug("Could not find the role of the caller - role based throttling NOT applied"); } } } return canAccess; }
/** * processing through the throttle 1) concurrent throttling 2) access rate based throttling - * domain or ip * * @param throttle The Throttle object - holds all configuration and state data of the throttle * @param messageContext The MessageContext , that holds all data per message basis * @throws AxisFault Throws when access must deny for caller * @throws ThrottleException ThrottleException */ public void process(Throttle throttle, MessageContext messageContext) throws ThrottleException, AxisFault { String throttleId = throttle.getId(); ConfigurationContext cc = messageContext.getConfigurationContext(); // check the env - whether clustered or not boolean isClusteringEnable = false; ClusteringAgent clusteringAgent = null; if (cc != null) { clusteringAgent = cc.getAxisConfiguration().getClusteringAgent(); } if (clusteringAgent != null && clusteringAgent.getStateManager() != null) { isClusteringEnable = true; } // Get the concurrent access controller ConcurrentAccessController cac; String key = null; if (isClusteringEnable) { // for clustered env.,gets it from axis configuration context key = ThrottleConstants.THROTTLE_PROPERTY_PREFIX + throttleId + ThrottleConstants.CAC_SUFFIX; cac = (ConcurrentAccessController) cc.getProperty(key); } else { // for non-clustered env.,gets it from axis configuration context cac = throttle.getConcurrentAccessController(); } // check for concurrent access boolean canAccess = doConcurrentThrottling(cac, messageContext); if (canAccess) { // if the concurrent access is success then // do the access rate based throttling if (messageContext.getFLOW() == MessageContext.IN_FLOW) { // gets the remote caller domain name String domain = null; HttpServletRequest request = (HttpServletRequest) messageContext.getPropertyNonReplicable(HTTPConstants.MC_HTTP_SERVLETREQUEST); if (request != null) { domain = request.getRemoteHost(); } // Domain name based throttling // check whether a configuration has been defined for this domain name or not String callerId = null; if (domain != null) { // loads the ThrottleContext ThrottleContext context = throttle.getThrottleContext(ThrottleConstants.DOMAIN_BASED_THROTTLE_KEY); if (context != null) { // Loads the ThrottleConfiguration ThrottleConfiguration config = context.getThrottleConfiguration(); if (config != null) { // check for configuration for this caller callerId = config.getConfigurationKeyOfCaller(domain); if (callerId != null) { // If this is a clustered env. if (isClusteringEnable) { context.setConfigurationContext(cc); context.setThrottleId(throttleId); } AccessInformation infor = accessRateController.canAccess( context, callerId, ThrottleConstants.DOMAIN_BASE); StatCollector.collect(infor, domain, ThrottleConstants.DOMAIN_BASE); // check for the permission for access if (!infor.isAccessAllowed()) { // In the case of both of concurrency throttling and // rate based throttling have enabled , // if the access rate less than maximum concurrent access , // then it is possible to occur death situation.To avoid that reset, // if the access has denied by rate based throttling if (cac != null) { cac.incrementAndGet(); // set back if this is a clustered env if (isClusteringEnable) { cc.setProperty(key, cac); // replicate the current state of ConcurrentAccessController try { if (debugOn) { log.debug( "Going to replicates the " + "states of the ConcurrentAccessController" + " with key : " + key); } Replicator.replicate(cc, new String[] {key}); } catch (ClusteringFault clusteringFault) { log.error("Error during replicating states ", clusteringFault); } } } throw new AxisFault( " Access deny for a " + "caller with Domain " + domain + " " + " : Reason : " + infor.getFaultReason()); } } else { if (debugOn) { log.debug( "Could not find the Throttle Context for domain-Based " + "Throttling for domain name " + domain + " Throttling for this " + "domain name may not be configured from policy"); } } } } } else { if (debugOn) { log.debug("Could not find the domain of the caller - IP-based throttling may occur"); } } // IP based throttling - Only if there is no configuration for caller domain name if (callerId == null) { String ip = (String) messageContext.getProperty(MessageContext.REMOTE_ADDR); if (ip != null) { // loads IP based throttle context ThrottleContext context = throttle.getThrottleContext(ThrottleConstants.IP_BASED_THROTTLE_KEY); if (context != null) { // Loads the ThrottleConfiguration ThrottleConfiguration config = context.getThrottleConfiguration(); if (config != null) { // check for configuration for this ip callerId = config.getConfigurationKeyOfCaller(ip); if (callerId != null) { // for clustered env. if (isClusteringEnable) { context.setConfigurationContext(cc); context.setThrottleId(throttleId); } AccessInformation infor = accessRateController.canAccess(context, callerId, ThrottleConstants.IP_BASE); // check for the permission for access StatCollector.collect(infor, ip, ThrottleConstants.IP_BASE); if (!infor.isAccessAllowed()) { // In the case of both of concurrency throttling and // rate based throttling have enabled , // if the access rate less than maximum concurrent access , // then it is possible to occur death situation.To avoid that reset, // if the access has denied by rate based throttling if (cac != null) { cac.incrementAndGet(); // set back if this is a clustered env if (isClusteringEnable) { cc.setProperty(key, cac); // replicate the current state of ConcurrentAccessController try { if (debugOn) { log.debug( "Going to replicates the " + "states of the ConcurrentAccessController" + " with key : " + key); } Replicator.replicate(cc, new String[] {key}); } catch (ClusteringFault clusteringFault) { log.error("Error during replicating states ", clusteringFault); } } } throw new AxisFault( " Access deny for a " + "caller with IP " + ip + " " + " : Reason : " + infor.getFaultReason()); } } } } else { if (debugOn) { log.debug("Could not find the throttle Context for IP-Based throttling"); } } } else { if (debugOn) { log.debug( "Could not find the IP address of the caller " + "- throttling will not occur"); } } } } // all the replication functionality of the access rate based throttling handles by itself // just replicate the current state of ConcurrentAccessController if (isClusteringEnable && cac != null) { try { if (debugOn) { log.debug( "Going to replicates the states of the ConcurrentAccessController" + " with key : " + key); } Replicator.replicate(cc, new String[] {key}); } catch (ClusteringFault clusteringFault) { log.error("Error during replicating states ", clusteringFault); } } // finally engage rolebased access throttling if available doRoleBasedAccessThrottling(throttle, messageContext, isClusteringEnable); } else { // replicate the current state of ConcurrentAccessController if (isClusteringEnable) { try { if (debugOn) { log.debug( "Going to replicates the states of the ConcurrentAccessController" + " with key : " + key); } Replicator.replicate(cc, new String[] {key}); } catch (ClusteringFault clusteringFault) { log.error("Error during replicating states ", clusteringFault); } } throw new AxisFault( "Access has currently been denied since " + " maximum concurrent access have exceeded"); } }